androidx.compose.material3

Build Jetpack Compose UIs with Material Design 3, the next evolution of Material Design. Material 3 includes updated theming and components and Material You personalization features like dynamic color, and is designed to be cohesive with the new Android 12 visual style and system UI.

Material You image

In this page, you'll find documentation for types, properties, and functions available in the androidx.compose.material3 package.

For more information, check out Material Design 3 in Compose.

Overview

Theming

APIs Description
Material Theming MaterialTheme M3 theme
Color scheme ColorScheme M3 color scheme
lightColorScheme M3 light color scheme
darkColorScheme M3 dark color scheme
Dynamic color dynamicLightColorScheme M3 dynamic light color scheme
dynamicDarkColorScheme M3 dynamic dark color scheme
Typography Typography M3 typography
Shape Shapes M3 shape

Components

APIs Description
Badge Badge M3 badge
BadgedBox M3 badged box
Bottom app bar BottomAppBar M3 bottom app bar
Bottom sheet BottomSheetScaffold M3 bottom sheet
ModalBottomSheet M3 modal bottom sheet
Buttons Button M3 filled button
ElevatedButton M3 elevated button
FilledTonalButton M3 filled tonal button
OutlinedButton M3 outlined button
TextButton M3 text button
Cards Card M3 filled card
ElevatedCard M3 elevated card
OutlinedCard M3 outlined card
Checkbox Checkbox M3 checkbox
TriStateCheckbox M3 indeterminate checkbox
Chips AssistChip M3 assist chip
ElevatedAssistChip M3 elevated assist chip
FilterChip M3 filter chip
ElevatedFilterChip M3 elevated filter chip
InputChip M3 input chip
SuggestionChip M3 suggestion chip
ElevatedSuggestionChip M3 elevated suggestion chip
Date Picker DatePicker M3 date picker
DatePickerDialog M3 date picker embeeded in dialog
DateRangePicker M3 date range picker
Dialogs AlertDialog M3 basic dialog
Dividers HorizontalDivider M3 horizontal divider
VerticalDivider M3 vertical divider
Extended FAB ExtendedFloatingActionButton M3 extended FAB
FAB FloatingActionButton M3 FAB
SmallFloatingActionButton M3 small FAB
LargeFloatingActionButton M3 large FAB
Icon button IconButton M3 standard icon button
IconToggleButton M3 standard icon toggle button
FilledIconButton M3 filled icon button
FilledIconToggleButton M3 filled icon toggle button
FilledTonalIconButton M3 filled tonal icon button
FilledTonalIconToggleButton M3 filled tonal icon toggle button
OutlinedIconButton M3 outlined icon button
OutlinedIconToggleButton M3 outlined icon toggle button
Lists ListItem M3 list item
Menus DropdownMenu M3 menu
DropdownMenuItem M3 menu item
ExposedDropdownMenuBox M3 exposed dropdown menu
Navigation bar NavigationBar M3 navigation bar
NavigationBarItem M3 navigation bar item
Navigation drawer ModalNavigationDrawer M3 modal navigation drawer
ModalDrawerSheet M3 modal drawer sheet
PermanentNavigationDrawer M3 permanent standard navigation drawer
PermanentDrawerSheet M3 permanent standard drawer sheet
DismissibleNavigationDrawer M3 dismissible standard navigation drawer
DismissibleDrawerSheet M3 dismissible standard drawer sheet
NavigationDrawerItem M3 navigation drawer item
Navigation rail NavigationRail M3 navigation rail
NavigationRailItem M3 navigation rail item
Progress indicators LinearProgressIndicator M3 linear progress indicator
CircularProgressIndicator M3 circular progress indicator
Radio button RadioButton M3 radio button
Search Bar SearchBar M3 search bar
DockedSearchBar M3 docked search bar
Segmented Button SegmentedButton M3 segmented button
SingleChoiceSegmentedButtonRow M3 single choice segmented button row
MultiChoiceSegmentedButtonRow M3 multiple choice segmented button row
Sliders Slider M3 slider
RangeSlider M3 range slider
Snackbars Snackbar M3 snackbar
Swipe to Dismiss SwipeToDismiss M3 swipe to dismiss
Switch Switch M3 switch
Tabs Tab M3 tab
LeadingIconTab M3 leading icon tab
PrimaryIndicator M3 primary tab indicator
PrimaryTabRow M3 primary tab row
SecondaryIndicator M3 secondary tab indicator
SecondaryTabRow M3 secondary tab row
TabRow M3 fixed tab row
ScrollableTabRow M3 scrollable tab row
Text fields TextField M3 filled text field
OutlinedTextField M3 outlined text field
Time Picker TimePicker M3 time picker
TimeInput M3 time input
Tool tip PlainTooltipBox M3 plain tool tip
RichTooltipBox M3 rich tool tip
Top app bar TopAppBar M3 small top app bar
CenterAlignedTopAppBar M3 center-aligned top app bar
MediumTopAppBar M3 medium top app bar
LargeTopAppBar M3 large top app bar

Surfaces and layout

APIs Description
Surfaces Surface M3 surface
Scaffold Scaffold M3 layout

Icons and text

APIs Description
Icon Icon M3 icon
Text Text M3 text

Also check out the androidx.compose.material.icons package.

Interfaces

BottomAppBarScrollBehavior

A BottomAppBarScrollBehavior defines how a bottom app bar should behave when the content under it is scrolled.

Cmn
BottomAppBarState

A state object that can be hoisted to control and observe the bottom app bar state.

Cmn
ButtonGroupScope

Button group scope used to indicate a Modifier.weight of a child element.

Cmn
DatePickerFormatter

A date formatter interface used by DatePicker.

Cmn
DatePickerState

A state object that can be hoisted to observe the date picker state.

Cmn
DateRangePickerState

A state object that can be hoisted to observe the date range picker state.

Cmn
FloatingActionButtonMenuScope

Scope for the children of FloatingActionButtonMenu

Cmn
FloatingAppBarScrollBehavior

A FloatingAppBarScrollBehavior defines how a floating app bar should behave when the content under it is scrolled.

Cmn
FloatingAppBarState

A state object that can be hoisted to control and observe the floating app bar state.

Cmn
MotionScheme

A motion scheme provides all the FiniteAnimationSpecs for a MaterialTheme.

Cmn
MultiChoiceSegmentedButtonRowScope

Scope for the children of a MultiChoiceSegmentedButtonRow

Cmn
NavigationBarComponentOverride

Interface that allows libraries to override the behavior of the NavigationBar component.

Cmn
NavigationDrawerItemColors

Represents the colors of the various elements of a drawer item.

Cmn
NavigationRailComponentOverride

Interface that allows libraries to override the behavior of the NavigationRail component.

Cmn
SelectableDates

An interface that controls the selectable dates and years in the date pickers UI.

Cmn
SingleChoiceSegmentedButtonRowScope

Scope for the children of a SingleChoiceSegmentedButtonRow

Cmn
SnackbarData

Interface to represent the data of one particular Snackbar as a piece of the SnackbarHostState.

Cmn
SnackbarVisuals

Interface to represent the visuals of one particular Snackbar as a piece of the SnackbarData.

Cmn
TabIndicatorScope

Scope for the composable used to render a Tab indicator, this can be used for more complex indicators requiring layout information about the tabs like TabRowDefaults.PrimaryIndicator and TabRowDefaults.SecondaryIndicator

Cmn
TextFieldLabelScope

Scope for the label of a TextField or OutlinedTextField.

Cmn
TimePickerState

A state object that can be hoisted to observe the time picker state.

Cmn
ToggleFloatingActionButtonScope

Scope for the children of ToggleFloatingActionButton

Cmn
TooltipScope

Tooltip scope for TooltipBox to be used to obtain the LayoutCoordinates of the anchor content, and to draw a caret for the tooltip.

Cmn
TooltipState

The state that is associated with a TooltipBox.

Cmn
TopAppBarScrollBehavior

A TopAppBarScrollBehavior defines how an app bar should behave when the content under it is scrolled.

Cmn
WideNavigationRailState

A state object that can be hoisted to observe the wide navigation rail state.

Cmn

Classes

BottomSheetScaffoldState

State of the BottomSheetScaffold composable.

Cmn
ButtonColors

Represents the container and content colors used in a button in different states.

Cmn
ButtonElevation

Represents the elevation for a button in different states.

Cmn
ButtonShapes

The shapes that will be used in toggle buttons.

Cmn
CalendarLocale

Represents a Locale for the calendar.

Cmn
android
CardColors

Represents the container and content colors used in a card in different states.

Cmn
CardElevation

Represents the elevation for a card in different states.

Cmn
CheckboxColors

Represents the colors used by the three different sections (checkmark, box, and border) of a Checkbox or TriStateCheckbox in different states.

Cmn
ChipBorder

This class is deprecated. Maintained for binary compatibility.

Cmn
ChipColors

Represents the container and content colors used in a clickable chip in different states.

Cmn
ChipElevation

Represents the elevation used in a selectable chip in different states.

Cmn
ColorScheme

A color scheme holds all the named color parameters for a MaterialTheme.

Cmn
DatePickerColors

Represents the colors used by the date picker.

Cmn
DisplayMode

Represents the different modes that a date picker can be at.

Cmn
DragHandleColors

Specifies the colors that will be used in a drag handle in different states.

Cmn
DragHandleShapes

Specifies the shapes that will be used in a drag handle in different states.

Cmn
DragHandleSizes

Specifies the sizes that will be used in a drag handle in different states.

Cmn
DrawerState

State of the ModalNavigationDrawer and DismissibleNavigationDrawer composable.

Cmn
ExposedDropdownMenuAnchorType

The type of element that can serve as a dropdown menu anchor.

Cmn
ExposedDropdownMenuBoxScope

Scope for ExposedDropdownMenuBox.

Cmn
FabPosition

The possible positions for a FloatingActionButton attached to a Scaffold.

Cmn
FloatingActionButtonElevation

Represents the tonal and shadow elevation for a floating action button in different states.

Cmn
FloatingAppBarExitDirection

The possible directions for a HorizontalFloatingAppBar or VerticalFloatingAppBar, used to determine the exit direction when a FloatingAppBarScrollBehavior is attached.

Cmn
IconButtonColors

Represents the container and content colors used in an icon button in different states.

Cmn
IconButtonDefaults.IconButtonWidthOption

Class that describes the different supported widths of the IconButton.

Cmn
IconButtonShapes

The shapes that will be used in toggle buttons.

Cmn
IconToggleButtonColors

Represents the container and content colors used in a toggleable icon button in different states.

Cmn
ListItemColors

Represents the container and content colors used in a list item in different states.

Cmn
MaterialShapes

Holds predefined Material Design shapes as RoundedPolygons that can be used at various components as they are, or as part of a Morph.

Cmn
MenuItemColors

Represents the text and icon colors used in a menu item at different states.

Cmn
ModalBottomSheetProperties

Properties used to customize the behavior of a ModalBottomSheet.

Cmn
android
ModalWideNavigationRailProperties
Cmn
android
NavigationBarComponentOverrideContext

Parameters available to NavigationBar.

Cmn
NavigationBarItemColors

Represents the colors of the various elements of a navigation item.

Cmn
NavigationItemColors

Represents the colors of the various elements of a navigation item.

Cmn
NavigationItemIconPosition

Class that describes the different supported icon positions of the navigation item.

Cmn
NavigationRailComponentOverrideContext

Parameters available to NavigationRail.

Cmn
NavigationRailItemColors

Represents the colors of the various elements of a navigation item.

Cmn
RadioButtonColors

Represents the color used by a RadioButton in different states.

Cmn
RangeSliderState

Class that holds information about RangeSlider's active range.

Cmn
RichTooltipColors
Cmn
RippleConfiguration

Configuration for ripple appearance, provided using LocalRippleConfiguration.

Cmn
SearchBarColors

Represents the colors used by a search bar in different states.

Cmn
SegmentedButtonColors

The different colors used in parts of the SegmentedButton in different states

Cmn
SelectableChipColors

Represents the container and content colors used in a selectable chip in different states.

Cmn
SelectableChipElevation

Represents the elevation used in a selectable chip in different states.

Cmn
Shapes

Material surfaces can be displayed in different shapes.

Cmn
SheetState

State of a sheet composable, such as ModalBottomSheet

Cmn
ShortNavigationBarArrangement

Class that describes the different supported item arrangements of the ShortNavigationBar.

Cmn
SliderColors

Represents the color used by a Slider in different states.

Cmn
SliderPositions

This class is deprecated. Not necessary with the introduction of Slider state

Cmn
SliderState

Class that holds information about Slider's active range.

Cmn
SnackbarHostState

State of the SnackbarHost, which controls the queue and the current Snackbar being shown inside the SnackbarHost.

Cmn
SplitButtonShapes

The shapes that will be used in SplitButtonLayout.

Cmn
SwipeToDismissBoxState

State of the SwipeToDismissBox composable.

Cmn
SwitchColors

Represents the colors used by a Switch in different states

Cmn
TabPosition

Data class that contains information about a tab's position on screen, used for calculating where to place the indicator that shows which tab is selected.

Cmn
TextFieldColors

Represents the colors of the input text, container, and content (including label, placeholder, leading and trailing icons) used in a text field in different states.

Cmn
TextFieldLabelPosition

The position of the label with respect to the text field.

Cmn
TextFieldLabelPosition.Above

The label is positioned above and outside the text field container.

Cmn
TextFieldLabelPosition.Attached

The default label position according to the Material specification.

Cmn
TimePickerColors

Represents the colors used by a TimePicker in different states

Cmn
TimePickerLayoutType

Represents the different configurations for the layout of the Time Picker

Cmn
TimePickerSelectionMode

The selection mode for the time picker

Cmn
ToggleButtonColors

Represents the container and content colors used in a toggle button in different states.

Cmn
TopAppBarColors

Represents the colors used by a top app bar in different states.

Cmn
TopAppBarState

A state object that can be hoisted to control and observe the top app bar state.

Cmn
TopAppBarTitleAlignment

This class defines ways title and subtitle can be aligned along a TopAppBar's main axis.

Cmn
Typography

The Material Design type scale includes a range of contrasting styles that support the needs of your product and its content.

Cmn
WideNavigationRailArrangement

Class that describes the different supported item arrangements of the WideNavigationRail.

Cmn
WideNavigationRailColors

Represents the colors of the various elements of a wide navigation rail.

Cmn

Objects

AlertDialogDefaults

Contains default values used for AlertDialog and BasicAlertDialog.

Cmn
AssistChipDefaults

Contains the baseline values used by AssistChip.

Cmn
BadgeDefaults

Default values used for Badge implementations.

Cmn
BottomAppBarDefaults

Contains default values used for the bottom app bar implementations.

Cmn
BottomSheetDefaults

Contains the default values used by ModalBottomSheet and BottomSheetScaffold.

Cmn
ButtonDefaults

Contains the default values used by all 5 button types.

Cmn
ButtonGroupDefaults

Default values used by ButtonGroup

Cmn
CardDefaults

Contains the default values used by all card types.

Cmn
CheckboxDefaults

Defaults used in Checkbox and TriStateCheckbox.

Cmn
DatePickerDefaults

Contains default values used by the DatePicker.

Cmn
DateRangePickerDefaults

Contains default values used by the DateRangePicker.

Cmn
DefaultNavigationBarComponentOverride

NavigationBarComponentOverride used when no override is specified.

Cmn
DefaultNavigationRailComponentOverride

NavigationRailComponentOverride used when no override is specified.

Cmn
DividerDefaults

Default values for Divider

Cmn
DrawerDefaults

Object to hold default values for ModalNavigationDrawer

Cmn
ExposedDropdownMenuDefaults

Contains default values used by Exposed Dropdown Menu.

Cmn
FilterChipDefaults

Contains the baseline values used by FilterChip.

Cmn
FloatingActionButtonDefaults

Contains the default values used by FloatingActionButton

Cmn
FloatingAppBarDefaults

Contains default values used for the floating app bar implementations.

Cmn
IconButtonDefaults

Contains the default values for all four icon and icon toggle button types.

Cmn
InputChipDefaults

Contains the baseline values used by an InputChip.

Cmn
ListItemDefaults

Contains the default values used by list items.

Cmn
LoadingIndicatorDefaults

Contains default values by the LoadingIndicator.

Cmn
MaterialTheme

Contains functions to access the current theme values provided at the call site's position in the hierarchy.

Cmn
MenuDefaults

Contains default values used for DropdownMenu and DropdownMenuItem.

Cmn
ModalBottomSheetDefaults

Default values for ModalBottomSheet

Cmn
android
ModalWideNavigationRailDefaults

Default values for ModalWideNavigationRail.

Cmn
NavigationBarDefaults

Defaults used in NavigationBar.

Cmn
NavigationBarItemDefaults

Defaults used in NavigationBarItem.

Cmn
NavigationDrawerItemDefaults

Defaults used in NavigationDrawerItem.

Cmn
NavigationRailDefaults

Defaults used in NavigationRail

Cmn
NavigationRailItemDefaults

Defaults used in NavigationRailItem.

Cmn
OutlinedTextFieldDefaults

Contains the default values used by OutlinedTextField.

Cmn
ProgressIndicatorDefaults

Contains the default values used for LinearProgressIndicator and CircularProgressIndicator.

Cmn
RadioButtonDefaults

Defaults used in RadioButton.

Cmn
RippleDefaults

Default values used by ripple.

Cmn
ScaffoldDefaults

Object containing various default values for Scaffold component.

Cmn
SearchBarDefaults

Defaults used in SearchBar and DockedSearchBar.

Cmn
SegmentedButtonDefaults
Cmn
ShapeDefaults

Contains the default values used by Shapes

Cmn
ShortNavigationBarDefaults

Defaults used in ShortNavigationBar.

Cmn
ShortNavigationBarItemDefaults

Defaults used in ShortNavigationBarItem.

Cmn
SliderDefaults

Object to hold defaults used by Slider

Cmn
SnackbarDefaults

Contains the default values used for Snackbar.

Cmn
SplitButtonDefaults

Contains default values used by SplitButtonLayout and its style variants.

Cmn
SuggestionChipDefaults

Contains the baseline values used by SuggestionChip.

Cmn
SwipeToDismissBoxDefaults

Contains default values for SwipeToDismissBox and SwipeToDismissBoxState.

Cmn
SwitchDefaults

Contains the default values used by Switch

Cmn
TabRowDefaults

Contains default implementations and values used for TabRow.

Cmn
TextFieldDefaults

Contains the default values used by TextField.

Cmn
TimePickerDefaults

Contains the default values used by TimePicker

Cmn
ToggleButtonDefaults

Contains the default values for all five toggle button types.

Cmn
ToggleFloatingActionButtonDefaults

Contains the default values used by ToggleFloatingActionButton

Cmn
TooltipDefaults

Tooltip defaults that contain default values for both PlainTooltip and RichTooltip

Cmn
TopAppBarDefaults

Contains default values used for the top app bar implementations.

Cmn
VerticalDragHandleDefaults

Contains the baseline values used by a VerticalDragHandle.

Cmn
WavyProgressIndicatorDefaults

Contains the default values used for wavy progress indicators

Cmn
WideNavigationRailDefaults

Defaults used in WideNavigationRail.

Cmn
WideNavigationRailItemDefaults

Defaults used in WideNavigationRailItem.

Cmn

Annotations

Enums

DrawerValue

Possible values of DrawerState.

Cmn
SheetValue

Possible values of SheetState.

Cmn
SnackbarDuration

Possible durations of the Snackbar in SnackbarHost

Cmn
SnackbarResult

Possible results of the SnackbarHostState.showSnackbar call

Cmn
SwipeToDismissBoxValue

The directions in which a SwipeToDismissBox can be dismissed.

Cmn
WideNavigationRailValue

Possible values of WideNavigationRailState.

Cmn

Type aliases

CalendarLocale

Represents a Locale for the calendar.

android
MenuAnchorType

This type alias is deprecated. Renamed to ExposedDropdownMenuAnchorType

Cmn

Top-level functions summary

Unit
@ExperimentalMaterial3Api
@Composable
AlertDialog(
    onDismissRequest: () -> Unit,
    modifier: Modifier,
    properties: DialogProperties,
    content: @Composable () -> Unit
)

This function is deprecated. Use BasicAlertDialog instead

Cmn
Unit
@Composable
AlertDialog(
    onDismissRequest: () -> Unit,
    confirmButton: @Composable () -> Unit,
    modifier: Modifier,
    dismissButton: (@Composable () -> Unit)?,
    icon: (@Composable () -> Unit)?,
    title: (@Composable () -> Unit)?,
    text: (@Composable () -> Unit)?,
    shape: Shape,
    containerColor: Color,
    iconContentColor: Color,
    titleContentColor: Color,
    textContentColor: Color,
    tonalElevation: Dp,
    properties: DialogProperties
)

Material Design basic dialog.

Cmn
android
Unit
@Composable
AssistChip(
    onClick: () -> Unit,
    label: @Composable () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    leadingIcon: (@Composable () -> Unit)?,
    trailingIcon: (@Composable () -> Unit)?,
    shape: Shape,
    colors: ChipColors,
    elevation: ChipElevation?,
    border: BorderStroke?,
    interactionSource: MutableInteractionSource?
)

Material Design assist chip.

Cmn
Unit
@Composable
Badge(
    modifier: Modifier,
    containerColor: Color,
    contentColor: Color,
    content: (@Composable RowScope.() -> Unit)?
)

A badge represents dynamic information such as a number of pending requests in a navigation bar.

Cmn
Unit
@Composable
BadgedBox(
    badge: @Composable BoxScope.() -> Unit,
    modifier: Modifier,
    content: @Composable BoxScope.() -> Unit
)

Material Design badge box.

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
BasicAlertDialog(
    onDismissRequest: () -> Unit,
    modifier: Modifier,
    properties: DialogProperties,
    content: @Composable () -> Unit
)

Basic alert dialog dialog.

Cmn
Unit
@Composable
BottomAppBar(
    modifier: Modifier,
    containerColor: Color,
    contentColor: Color,
    tonalElevation: Dp,
    contentPadding: PaddingValues,
    windowInsets: WindowInsets,
    content: @Composable RowScope.() -> Unit
)

Material Design bottom app bar.

Cmn
Unit
@Composable
BottomAppBar(
    actions: @Composable RowScope.() -> Unit,
    modifier: Modifier,
    floatingActionButton: (@Composable () -> Unit)?,
    containerColor: Color,
    contentColor: Color,
    tonalElevation: Dp,
    contentPadding: PaddingValues,
    windowInsets: WindowInsets
)

Material Design bottom app bar.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
BottomAppBar(
    horizontalArrangement: Arrangement.Horizontal,
    modifier: Modifier,
    containerColor: Color,
    contentColor: Color,
    contentPadding: PaddingValues,
    windowInsets: WindowInsets,
    scrollBehavior: BottomAppBarScrollBehavior?,
    content: @Composable RowScope.() -> Unit
)

Material Design bottom app bar.

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
BottomAppBar(
    modifier: Modifier,
    containerColor: Color,
    contentColor: Color,
    tonalElevation: Dp,
    contentPadding: PaddingValues,
    windowInsets: WindowInsets,
    scrollBehavior: BottomAppBarScrollBehavior?,
    content: @Composable RowScope.() -> Unit
)

Material Design bottom app bar.

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
BottomAppBar(
    actions: @Composable RowScope.() -> Unit,
    modifier: Modifier,
    floatingActionButton: (@Composable () -> Unit)?,
    containerColor: Color,
    contentColor: Color,
    tonalElevation: Dp,
    contentPadding: PaddingValues,
    windowInsets: WindowInsets,
    scrollBehavior: BottomAppBarScrollBehavior?
)

Material Design bottom app bar.

Cmn
BottomAppBarState
@ExperimentalMaterial3Api
BottomAppBarState(
    initialHeightOffsetLimit: Float,
    initialHeightOffset: Float,
    initialContentOffset: Float
)

Creates a BottomAppBarState.

Cmn
Unit
@Composable
@ExperimentalMaterial3Api
BottomSheetScaffold(
    sheetContent: @Composable ColumnScope.() -> Unit,
    modifier: Modifier,
    scaffoldState: BottomSheetScaffoldState,
    sheetPeekHeight: Dp,
    sheetMaxWidth: Dp,
    sheetShape: Shape,
    sheetContainerColor: Color,
    sheetContentColor: Color,
    sheetTonalElevation: Dp,
    sheetShadowElevation: Dp,
    sheetDragHandle: (@Composable () -> Unit)?,
    sheetSwipeEnabled: Boolean,
    topBar: (@Composable () -> Unit)?,
    snackbarHost: @Composable (SnackbarHostState) -> Unit,
    containerColor: Color,
    contentColor: Color,
    content: @Composable (PaddingValues) -> Unit
)

Material Design standard bottom sheet scaffold.

Cmn
Unit
@Composable
Button(
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shape: Shape,
    colors: ButtonColors,
    elevation: ButtonElevation?,
    border: BorderStroke?,
    contentPadding: PaddingValues,
    interactionSource: MutableInteractionSource?,
    content: @Composable RowScope.() -> Unit
)

Material Design button.

Cmn
Unit
@Composable
@ExperimentalMaterial3ExpressiveApi
ButtonGroup(
    modifier: Modifier,
    animateFraction: @FloatRange(from = 0.0) Float,
    horizontalArrangement: Arrangement.Horizontal,
    content: @Composable ButtonGroupScope.() -> Unit
)

TODO link to mio page when available.

Cmn
Unit
@Composable
Card(
    modifier: Modifier,
    shape: Shape,
    colors: CardColors,
    elevation: CardElevation,
    border: BorderStroke?,
    content: @Composable ColumnScope.() -> Unit
)

Material Design filled card.

Cmn
Unit
@Composable
Card(
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shape: Shape,
    colors: CardColors,
    elevation: CardElevation,
    border: BorderStroke?,
    interactionSource: MutableInteractionSource?,
    content: @Composable ColumnScope.() -> Unit
)

Material Design filled card.

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
CenterAlignedTopAppBar(
    title: @Composable () -> Unit,
    modifier: Modifier,
    navigationIcon: @Composable () -> Unit,
    actions: @Composable RowScope.() -> Unit,
    expandedHeight: Dp,
    windowInsets: WindowInsets,
    colors: TopAppBarColors,
    scrollBehavior: TopAppBarScrollBehavior?
)

Material Design center-aligned small top app bar.

Cmn
Unit
@Composable
Checkbox(
    checked: Boolean,
    onCheckedChange: ((Boolean) -> Unit)?,
    modifier: Modifier,
    enabled: Boolean,
    colors: CheckboxColors,
    interactionSource: MutableInteractionSource?
)

Material Design checkbox.

Cmn
Unit
@Composable
CircularProgressIndicator(
    modifier: Modifier,
    color: Color,
    strokeWidth: Dp,
    trackColor: Color,
    strokeCap: StrokeCap,
    gapSize: Dp
)

Indeterminate Material Design circular progress indicator.

Cmn
Unit
@Composable
CircularProgressIndicator(
    progress: Float,
    modifier: Modifier,
    color: Color,
    strokeWidth: Dp,
    trackColor: Color,
    strokeCap: StrokeCap
)

This function is deprecated. Use the overload that takes `progress` as a lambda

Cmn
Unit
@Composable
CircularProgressIndicator(
    progress: () -> Float,
    modifier: Modifier,
    color: Color,
    strokeWidth: Dp,
    trackColor: Color,
    strokeCap: StrokeCap,
    gapSize: Dp
)

Determinate Material Design circular progress indicator.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
CircularWavyProgressIndicator(
    modifier: Modifier,
    color: Color,
    trackColor: Color,
    stroke: Stroke,
    trackStroke: Stroke,
    gapSize: Dp,
    amplitude: @FloatRange(from = 0.0, to = 1.0) Float,
    wavelength: Dp,
    waveSpeed: Dp
)

Indeterminate Material Design circular progress indicator.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
CircularWavyProgressIndicator(
    progress: () -> Float,
    modifier: Modifier,
    color: Color,
    trackColor: Color,
    stroke: Stroke,
    trackStroke: Stroke,
    gapSize: Dp,
    amplitude: (progress: Float) -> Float,
    wavelength: Dp,
    waveSpeed: Dp
)

Determinate Material Design circular progress indicator.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
ContainedLoadingIndicator(
    modifier: Modifier,
    containerColor: Color,
    indicatorColor: Color,
    containerShape: Shape,
    polygons: List<RoundedPolygon>
)

A Material Design contained loading indicator.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
ContainedLoadingIndicator(
    progress: () -> Float,
    modifier: Modifier,
    containerColor: Color,
    indicatorColor: Color,
    containerShape: Shape,
    polygons: List<RoundedPolygon>
)

A Material Design contained loading indicator.

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
DatePicker(
    state: DatePickerState,
    modifier: Modifier,
    dateFormatter: DatePickerFormatter,
    colors: DatePickerColors,
    title: (@Composable () -> Unit)?,
    headline: (@Composable () -> Unit)?,
    showModeToggle: Boolean,
    requestFocus: Boolean
)

Material Design date picker.

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
DatePickerDialog(
    onDismissRequest: () -> Unit,
    confirmButton: @Composable () -> Unit,
    modifier: Modifier,
    dismissButton: (@Composable () -> Unit)?,
    shape: Shape,
    tonalElevation: Dp,
    colors: DatePickerColors,
    properties: DialogProperties,
    content: @Composable ColumnScope.() -> Unit
)

Material Design date picker dialog.

Cmn
android
DatePickerState
@ExperimentalMaterial3Api
DatePickerState(
    locale: CalendarLocale,
    initialSelectedDateMillis: Long?,
    initialDisplayedMonthMillis: Long?,
    yearRange: IntRange,
    initialDisplayMode: DisplayMode,
    selectableDates: SelectableDates
)

Creates a DatePickerState.

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
DateRangePicker(
    state: DateRangePickerState,
    modifier: Modifier,
    dateFormatter: DatePickerFormatter,
    colors: DatePickerColors,
    title: (@Composable () -> Unit)?,
    headline: (@Composable () -> Unit)?,
    showModeToggle: Boolean,
    requestFocus: Boolean
)

Material Design date range picker.

Cmn
DateRangePickerState
@ExperimentalMaterial3Api
DateRangePickerState(
    locale: CalendarLocale,
    initialSelectedStartDateMillis: Long?,
    initialSelectedEndDateMillis: Long?,
    initialDisplayedMonthMillis: Long?,
    yearRange: IntRange,
    initialDisplayMode: DisplayMode,
    selectableDates: SelectableDates
)

Creates a DateRangePickerState.

Cmn
Unit
@Composable
DismissibleDrawerSheet(
    modifier: Modifier,
    drawerShape: Shape,
    drawerContainerColor: Color,
    drawerContentColor: Color,
    drawerTonalElevation: Dp,
    windowInsets: WindowInsets,
    content: @Composable ColumnScope.() -> Unit
)

Content inside of a dismissible navigation drawer.

Cmn
Unit
@Composable
DismissibleDrawerSheet(
    drawerState: DrawerState,
    modifier: Modifier,
    drawerShape: Shape,
    drawerContainerColor: Color,
    drawerContentColor: Color,
    drawerTonalElevation: Dp,
    windowInsets: WindowInsets,
    content: @Composable ColumnScope.() -> Unit
)

Content inside of a dismissible navigation drawer.

Cmn
Unit
@Composable
DismissibleNavigationDrawer(
    drawerContent: @Composable () -> Unit,
    modifier: Modifier,
    drawerState: DrawerState,
    gesturesEnabled: Boolean,
    content: @Composable () -> Unit
)

Material Design navigation drawer.

Cmn
Unit
@Composable
Divider(modifier: Modifier, thickness: Dp, color: Color)

This function is deprecated. Renamed to HorizontalDivider

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
DockedSearchBar(
    inputField: @Composable () -> Unit,
    expanded: Boolean,
    onExpandedChange: (Boolean) -> Unit,
    modifier: Modifier,
    shape: Shape,
    colors: SearchBarColors,
    tonalElevation: Dp,
    shadowElevation: Dp,
    content: @Composable ColumnScope.() -> Unit
)

Material Design search.

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
DockedSearchBar(
    query: String,
    onQueryChange: (String) -> Unit,
    onSearch: (String) -> Unit,
    active: Boolean,
    onActiveChange: (Boolean) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    placeholder: (@Composable () -> Unit)?,
    leadingIcon: (@Composable () -> Unit)?,
    trailingIcon: (@Composable () -> Unit)?,
    shape: Shape,
    colors: SearchBarColors,
    tonalElevation: Dp,
    shadowElevation: Dp,
    interactionSource: MutableInteractionSource?,
    content: @Composable ColumnScope.() -> Unit
)

This function is deprecated. Use overload which takes inputField as a parameter

Cmn
Unit
@Composable
DropdownMenu(
    expanded: Boolean,
    onDismissRequest: () -> Unit,
    modifier: Modifier,
    offset: DpOffset,
    scrollState: ScrollState,
    properties: PopupProperties,
    shape: Shape,
    containerColor: Color,
    tonalElevation: Dp,
    shadowElevation: Dp,
    border: BorderStroke?,
    content: @Composable ColumnScope.() -> Unit
)

Material Design dropdown menu.

Cmn
android
Unit
@Composable
DropdownMenuItem(
    text: @Composable () -> Unit,
    onClick: () -> Unit,
    modifier: Modifier,
    leadingIcon: (@Composable () -> Unit)?,
    trailingIcon: (@Composable () -> Unit)?,
    enabled: Boolean,
    colors: MenuItemColors,
    contentPadding: PaddingValues,
    interactionSource: MutableInteractionSource?
)

Material Design dropdown menu item.

Cmn
android
Unit
@Composable
ElevatedAssistChip(
    onClick: () -> Unit,
    label: @Composable () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    leadingIcon: (@Composable () -> Unit)?,
    trailingIcon: (@Composable () -> Unit)?,
    shape: Shape,
    colors: ChipColors,
    elevation: ChipElevation?,
    border: BorderStroke?,
    interactionSource: MutableInteractionSource?
)

Material Design elevated assist chip.

Cmn
Unit
@Composable
ElevatedButton(
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shape: Shape,
    colors: ButtonColors,
    elevation: ButtonElevation?,
    border: BorderStroke?,
    contentPadding: PaddingValues,
    interactionSource: MutableInteractionSource?,
    content: @Composable RowScope.() -> Unit
)

Material Design elevated button.

Cmn
Unit
@Composable
ElevatedCard(
    modifier: Modifier,
    shape: Shape,
    colors: CardColors,
    elevation: CardElevation,
    content: @Composable ColumnScope.() -> Unit
)

Material Design elevated card.

Cmn
Unit
@Composable
ElevatedCard(
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shape: Shape,
    colors: CardColors,
    elevation: CardElevation,
    interactionSource: MutableInteractionSource?,
    content: @Composable ColumnScope.() -> Unit
)

Material Design elevated card.

Cmn
Unit
@Composable
ElevatedFilterChip(
    selected: Boolean,
    onClick: () -> Unit,
    label: @Composable () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    leadingIcon: (@Composable () -> Unit)?,
    trailingIcon: (@Composable () -> Unit)?,
    shape: Shape,
    colors: SelectableChipColors,
    elevation: SelectableChipElevation?,
    border: BorderStroke?,
    interactionSource: MutableInteractionSource?
)

Material Design elevated filter chip.

Cmn
Unit
@Composable
ElevatedSuggestionChip(
    onClick: () -> Unit,
    label: @Composable () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    icon: (@Composable () -> Unit)?,
    shape: Shape,
    colors: ChipColors,
    elevation: ChipElevation?,
    border: BorderStroke?,
    interactionSource: MutableInteractionSource?
)

Material Design elevated suggestion chip.

Cmn
Unit
@Composable
@ExperimentalMaterial3ExpressiveApi
ElevatedToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shapes: ButtonShapes,
    colors: ToggleButtonColors,
    elevation: ButtonElevation?,
    border: BorderStroke?,
    contentPadding: PaddingValues,
    interactionSource: MutableInteractionSource?,
    content: @Composable RowScope.() -> Unit
)

TODO link to mio page when available.

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
ExposedDropdownMenuBox(
    expanded: Boolean,
    onExpandedChange: (Boolean) -> Unit,
    modifier: Modifier,
    content: @Composable ExposedDropdownMenuBoxScope.() -> Unit
)

Material Design Exposed Dropdown Menu.

Cmn
Unit
@Composable
ExtendedFloatingActionButton(
    onClick: () -> Unit,
    modifier: Modifier,
    shape: Shape,
    containerColor: Color,
    contentColor: Color,
    elevation: FloatingActionButtonElevation,
    interactionSource: MutableInteractionSource?,
    content: @Composable RowScope.() -> Unit
)

Material Design extended floating action button.

Cmn
Unit
@Composable
ExtendedFloatingActionButton(
    text: @Composable () -> Unit,
    icon: @Composable () -> Unit,
    onClick: () -> Unit,
    modifier: Modifier,
    expanded: Boolean,
    shape: Shape,
    containerColor: Color,
    contentColor: Color,
    elevation: FloatingActionButtonElevation,
    interactionSource: MutableInteractionSource?
)

Material Design extended floating action button.

Cmn
Unit
@Composable
FilledIconButton(
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shape: Shape,
    colors: IconButtonColors,
    interactionSource: MutableInteractionSource?,
    content: @Composable () -> Unit
)

Material Design filled icon button.

Cmn
Unit
@Composable
FilledIconToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shape: Shape,
    colors: IconToggleButtonColors,
    interactionSource: MutableInteractionSource?,
    content: @Composable () -> Unit
)

Material Design filled icon toggle button.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
FilledIconToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    shapes: IconButtonShapes,
    modifier: Modifier,
    enabled: Boolean,
    colors: IconToggleButtonColors,
    interactionSource: MutableInteractionSource?,
    content: @Composable () -> Unit
)

Material Design filled icon toggle button.

Cmn
Unit
@Composable
FilledTonalButton(
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shape: Shape,
    colors: ButtonColors,
    elevation: ButtonElevation?,
    border: BorderStroke?,
    contentPadding: PaddingValues,
    interactionSource: MutableInteractionSource?,
    content: @Composable RowScope.() -> Unit
)

Material Design filled tonal button.

Cmn
Unit
@Composable
FilledTonalIconButton(
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shape: Shape,
    colors: IconButtonColors,
    interactionSource: MutableInteractionSource?,
    content: @Composable () -> Unit
)

Material Design filled tonal icon button.

Cmn
Unit
@Composable
FilledTonalIconToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shape: Shape,
    colors: IconToggleButtonColors,
    interactionSource: MutableInteractionSource?,
    content: @Composable () -> Unit
)

Material Design filled tonal icon toggle button.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
FilledTonalIconToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    shapes: IconButtonShapes,
    modifier: Modifier,
    enabled: Boolean,
    colors: IconToggleButtonColors,
    interactionSource: MutableInteractionSource?,
    content: @Composable () -> Unit
)

Material Design filled tonal icon toggle button.

Cmn
Unit
@Composable
FilterChip(
    selected: Boolean,
    onClick: () -> Unit,
    label: @Composable () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    leadingIcon: (@Composable () -> Unit)?,
    trailingIcon: (@Composable () -> Unit)?,
    shape: Shape,
    colors: SelectableChipColors,
    elevation: SelectableChipElevation?,
    border: BorderStroke?,
    interactionSource: MutableInteractionSource?
)

Material Design filter chip.

Cmn
Unit
@Composable
FloatingActionButton(
    onClick: () -> Unit,
    modifier: Modifier,
    shape: Shape,
    containerColor: Color,
    contentColor: Color,
    elevation: FloatingActionButtonElevation,
    interactionSource: MutableInteractionSource?,
    content: @Composable () -> Unit
)

Material Design floating action button.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
FloatingActionButtonMenu(
    expanded: Boolean,
    button: @Composable () -> Unit,
    modifier: Modifier,
    horizontalAlignment: Alignment.Horizontal,
    content: @Composable FloatingActionButtonMenuScope.() -> Unit
)

FAB Menus should be used in conjunction with a ToggleFloatingActionButton to provide additional choices to the user after clicking a FAB.

Cmn
FloatingAppBarState
@ExperimentalMaterial3ExpressiveApi
FloatingAppBarState(
    initialOffsetLimit: Float,
    initialOffset: Float,
    initialContentOffset: Float
)

Creates a FloatingAppBarState.

Cmn
Unit
@Composable
HorizontalDivider(modifier: Modifier, thickness: Dp, color: Color)

Material Design divider.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
HorizontalFloatingAppBar(
    expanded: Boolean,
    modifier: Modifier,
    containerColor: Color,
    contentPadding: PaddingValues,
    scrollBehavior: FloatingAppBarScrollBehavior?,
    shape: Shape,
    leadingContent: (@Composable RowScope.() -> Unit)?,
    trailingContent: (@Composable RowScope.() -> Unit)?,
    content: @Composable RowScope.() -> Unit
)
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.FloatingAppBarDefaults.ScreenOffset
import androidx.compose.material3.FloatingAppBarExitDirection.Companion.Bottom
import androidx.compose.material3.HorizontalFloatingAppBar
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment.Companion.BottomCenter
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp

val context = LocalContext.current
val isTouchExplorationEnabled = remember {
    val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
    am.isEnabled && am.isTouchExplorationEnabled
}
val listState = rememberLazyListState()
var currentItem = 0
val expanded by remember {
    derivedStateOf {
        val temp = currentItem
        currentItem = listState.firstVisibleItemIndex
        listState.firstVisibleItemIndex <= temp // true if the list is scrolled up
    }
}
Scaffold(
    content = { innerPadding ->
        Box {
            LazyColumn(
                state = listState,
                contentPadding = innerPadding,
                verticalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                val list = (0..75).map { it.toString() }
                items(count = list.size) {
                    Text(
                        text = list[it],
                        style = MaterialTheme.typography.bodyLarge,
                        modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                    )
                }
            }
            HorizontalFloatingAppBar(
                modifier = Modifier.align(BottomCenter).offset(y = -ScreenOffset),
                expanded = expanded || isTouchExplorationEnabled,
                leadingContent = { leadingContent() },
                trailingContent = { trailingContent() },
                content = {
                    FilledIconButton(
                        modifier = Modifier.width(64.dp),
                        onClick = { /* doSomething() */ }
                    ) {
                        Icon(Icons.Filled.Add, contentDescription = "Localized description")
                    }
                },
            )
        }
    }
)
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.FloatingAppBarDefaults
import androidx.compose.material3.FloatingAppBarDefaults.ScreenOffset
import androidx.compose.material3.FloatingAppBarExitDirection.Companion.Bottom
import androidx.compose.material3.HorizontalFloatingAppBar
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment.Companion.BottomCenter
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp

val context = LocalContext.current
val isTouchExplorationEnabled = remember {
    val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
    am.isEnabled && am.isTouchExplorationEnabled
}
val listState = rememberLazyListState()
val exitAlwaysScrollBehavior =
    FloatingAppBarDefaults.exitAlwaysScrollBehavior(exitDirection = Bottom)
Scaffold(
    modifier = Modifier.nestedScroll(exitAlwaysScrollBehavior),
    content = { innerPadding ->
        Box {
            LazyColumn(
                state = listState,
                contentPadding = innerPadding,
                verticalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                val list = (0..75).map { it.toString() }
                items(count = list.size) {
                    Text(
                        text = list[it],
                        style = MaterialTheme.typography.bodyLarge,
                        modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                    )
                }
            }
            HorizontalFloatingAppBar(
                modifier = Modifier.align(BottomCenter).offset(y = -ScreenOffset),
                expanded = true,
                leadingContent = { leadingContent() },
                trailingContent = { trailingContent() },
                content = {
                    FilledIconButton(
                        modifier = Modifier.width(64.dp),
                        onClick = { /* doSomething() */ }
                    ) {
                        Icon(Icons.Filled.Add, contentDescription = "Localized description")
                    }
                },
                scrollBehavior =
                    if (!isTouchExplorationEnabled) exitAlwaysScrollBehavior else null,
            )
        }
    }
)
Cmn
Unit
@Composable
Icon(
    bitmap: ImageBitmap,
    contentDescription: String?,
    modifier: Modifier,
    tint: Color
)

A Material Design icon component that draws bitmap using tint, with a default value of LocalContentColor.

Cmn
Unit
@Composable
Icon(
    imageVector: ImageVector,
    contentDescription: String?,
    modifier: Modifier,
    tint: Color
)

A Material Design icon component that draws imageVector using tint, with a default value of LocalContentColor.

Cmn
Unit
@Composable
Icon(
    painter: Painter,
    contentDescription: String?,
    modifier: Modifier,
    tint: Color
)

A Material Design icon component that draws painter using tint, with a default value of LocalContentColor.

Cmn
Unit
@Composable
@ExperimentalMaterial3Api
Icon(
    painter: Painter,
    tint: ColorProducer?,
    contentDescription: String?,
    modifier: Modifier
)

A Material Design icon component that draws painter using tint.

Cmn
Unit
@Composable
IconButton(
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    colors: IconButtonColors,
    interactionSource: MutableInteractionSource?,
    shape: Shape,
    content: @Composable () -> Unit
)

Material Design standard icon button.

Cmn
Unit
@Composable
IconToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    colors: IconToggleButtonColors,
    interactionSource: MutableInteractionSource?,
    shape: Shape,
    content: @Composable () -> Unit
)

Material Design standard icon toggle button.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
IconToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    shapes: IconButtonShapes,
    modifier: Modifier,
    enabled: Boolean,
    colors: IconToggleButtonColors,
    interactionSource: MutableInteractionSource?,
    content: @Composable () -> Unit
)

Material Design standard icon toggle button.

Cmn
Unit
@Composable
InputChip(
    selected: Boolean,
    onClick: () -> Unit,
    label: @Composable () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    leadingIcon: (@Composable () -> Unit)?,
    avatar: (@Composable () -> Unit)?,
    trailingIcon: (@Composable () -> Unit)?,
    shape: Shape,
    colors: SelectableChipColors,
    elevation: SelectableChipElevation?,
    border: BorderStroke?,
    interactionSource: MutableInteractionSource?
)

Material Design input chip.

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
Label(
    label: @Composable TooltipScope.() -> Unit,
    modifier: Modifier,
    interactionSource: MutableInteractionSource?,
    isPersistent: Boolean,
    content: @Composable () -> Unit
)

Label component that will append a label to content.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
LargeExtendedFloatingActionButton(
    onClick: () -> Unit,
    modifier: Modifier,
    shape: Shape,
    containerColor: Color,
    contentColor: Color,
    elevation: FloatingActionButtonElevation,
    interactionSource: MutableInteractionSource?,
    content: @Composable RowScope.() -> Unit
)

Material Design large extended floating action button.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
LargeExtendedFloatingActionButton(
    text: @Composable () -> Unit,
    icon: @Composable () -> Unit,
    onClick: () -> Unit,
    modifier: Modifier,
    expanded: Boolean,
    shape: Shape,
    containerColor: Color,
    contentColor: Color,
    elevation: FloatingActionButtonElevation,
    interactionSource: MutableInteractionSource?
)

Material Design large extended floating action button.

Cmn
Unit
@Composable
LargeFloatingActionButton(
    onClick: () -> Unit,
    modifier: Modifier,
    shape: Shape,
    containerColor: Color,
    contentColor: Color,
    elevation: FloatingActionButtonElevation,
    interactionSource: MutableInteractionSource?,
    content: @Composable () -> Unit
)

Material Design large floating action button.

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
LargeTopAppBar(
    title: @Composable () -> Unit,
    modifier: Modifier,
    navigationIcon: @Composable () -> Unit,
    actions: @Composable RowScope.() -> Unit,
    collapsedHeight: Dp,
    expandedHeight: Dp,
    windowInsets: WindowInsets,
    colors: TopAppBarColors,
    scrollBehavior: TopAppBarScrollBehavior?
)

Material Design large top app bar.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
LargeTopAppBar(
    title: @Composable () -> Unit,
    subtitle: (@Composable () -> Unit)?,
    modifier: Modifier,
    navigationIcon: @Composable () -> Unit,
    actions: @Composable RowScope.() -> Unit,
    titleHorizontalAlignment: TopAppBarTitleAlignment,
    collapsedHeight: Dp,
    expandedHeight: Dp,
    windowInsets: WindowInsets,
    colors: TopAppBarColors,
    scrollBehavior: TopAppBarScrollBehavior?
)

Material Design large top app bar.

Cmn
Unit
@Composable
LeadingIconTab(
    selected: Boolean,
    onClick: () -> Unit,
    text: @Composable () -> Unit,
    icon: @Composable () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    selectedContentColor: Color,
    unselectedContentColor: Color,
    interactionSource: MutableInteractionSource?
)

Material Design tab.

Cmn
Unit
@Composable
LinearProgressIndicator(
    modifier: Modifier,
    color: Color,
    trackColor: Color,
    strokeCap: StrokeCap,
    gapSize: Dp
)

Indeterminate Material Design linear progress indicator.

Cmn
Unit
@Composable
LinearProgressIndicator(
    progress: Float,
    modifier: Modifier,
    color: Color,
    trackColor: Color,
    strokeCap: StrokeCap
)

This function is deprecated. Use the overload that takes `progress` as a lambda

Cmn
Unit
@Composable
LinearProgressIndicator(
    progress: () -> Float,
    modifier: Modifier,
    color: Color,
    trackColor: Color,
    strokeCap: StrokeCap,
    gapSize: Dp,
    drawStopIndicator: DrawScope.() -> Unit
)

Determinate Material Design linear progress indicator.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
LinearWavyProgressIndicator(
    modifier: Modifier,
    color: Color,
    trackColor: Color,
    stroke: Stroke,
    trackStroke: Stroke,
    gapSize: Dp,
    amplitude: @FloatRange(from = 0.0, to = 1.0) Float,
    wavelength: Dp,
    waveSpeed: Dp
)

Indeterminate Material Design linear wavy progress indicator.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
LinearWavyProgressIndicator(
    progress: () -> Float,
    modifier: Modifier,
    color: Color,
    trackColor: Color,
    stroke: Stroke,
    trackStroke: Stroke,
    gapSize: Dp,
    stopSize: Dp,
    amplitude: (progress: Float) -> Float,
    wavelength: Dp,
    waveSpeed: Dp
)

Determinate Material Design wavy linear progress indicator.

Cmn
Unit
@Composable
ListItem(
    headlineContent: @Composable () -> Unit,
    modifier: Modifier,
    overlineContent: (@Composable () -> Unit)?,
    supportingContent: (@Composable () -> Unit)?,
    leadingContent: (@Composable () -> Unit)?,
    trailingContent: (@Composable () -> Unit)?,
    colors: ListItemColors,
    tonalElevation: Dp,
    shadowElevation: Dp
)

Material Design list item.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
LoadingIndicator(
    modifier: Modifier,
    color: Color,
    polygons: List<RoundedPolygon>
)

A Material Design loading indicator.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
LoadingIndicator(
    progress: () -> Float,
    modifier: Modifier,
    color: Color,
    polygons: List<RoundedPolygon>
)

A Material Design loading indicator.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
MaterialExpressiveTheme(
    colorScheme: ColorScheme?,
    motionScheme: MotionScheme?,
    shapes: Shapes?,
    typography: Typography?,
    content: @Composable () -> Unit
)

Material Expressive Theming refers to the customization of your Material Design app to better reflect your product’s brand.

Cmn
Unit
@Composable
MaterialTheme(
    colorScheme: ColorScheme,
    shapes: Shapes,
    typography: Typography,
    content: @Composable () -> Unit
)

Material Theming refers to the customization of your Material Design app to better reflect your product’s brand.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
MaterialTheme(
    colorScheme: ColorScheme,
    motionScheme: MotionScheme,
    shapes: Shapes,
    typography: Typography,
    content: @Composable () -> Unit
)

Material Theming refers to the customization of your Material Design app to better reflect your product’s brand.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
MediumExtendedFloatingActionButton(
    onClick: () -> Unit,
    modifier: Modifier,
    shape: Shape,
    containerColor: Color,
    contentColor: Color,
    elevation: FloatingActionButtonElevation,
    interactionSource: MutableInteractionSource?,
    content: @Composable RowScope.() -> Unit
)

Material Design medium extended floating action button.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
MediumExtendedFloatingActionButton(
    text: @Composable () -> Unit,
    icon: @Composable () -> Unit,
    onClick: () -> Unit,
    modifier: Modifier,
    expanded: Boolean,
    shape: Shape,
    containerColor: Color,
    contentColor: Color,
    elevation: FloatingActionButtonElevation,
    interactionSource: MutableInteractionSource?
)

Material Design medium extended floating action button.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
MediumFloatingActionButton(
    onClick: () -> Unit,
    modifier: Modifier,
    shape: Shape,
    containerColor: Color,
    contentColor: Color,
    elevation: FloatingActionButtonElevation,
    interactionSource: MutableInteractionSource?,
    content: @Composable () -> Unit
)

Material Design medium floating action button.

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
MediumTopAppBar(
    title: @Composable () -> Unit,
    modifier: Modifier,
    navigationIcon: @Composable () -> Unit,
    actions: @Composable RowScope.() -> Unit,
    collapsedHeight: Dp,
    expandedHeight: Dp,
    windowInsets: WindowInsets,
    colors: TopAppBarColors,
    scrollBehavior: TopAppBarScrollBehavior?
)

Material Design medium top app bar.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
MediumTopAppBar(
    title: @Composable () -> Unit,
    subtitle: (@Composable () -> Unit)?,
    modifier: Modifier,
    navigationIcon: @Composable () -> Unit,
    actions: @Composable RowScope.() -> Unit,
    titleHorizontalAlignment: TopAppBarTitleAlignment,
    collapsedHeight: Dp,
    expandedHeight: Dp,
    windowInsets: WindowInsets,
    colors: TopAppBarColors,
    scrollBehavior: TopAppBarScrollBehavior?
)

Material Design medium top app bar.

Cmn
Unit
@Composable
@ExperimentalMaterial3Api
ModalBottomSheet(
    onDismissRequest: () -> Unit,
    modifier: Modifier,
    sheetState: SheetState,
    sheetMaxWidth: Dp,
    sheetGesturesEnabled: Boolean,
    shape: Shape,
    containerColor: Color,
    contentColor: Color,
    tonalElevation: Dp,
    scrimColor: Color,
    dragHandle: (@Composable () -> Unit)?,
    contentWindowInsets: @Composable () -> WindowInsets,
    properties: ModalBottomSheetProperties,
    content: @Composable ColumnScope.() -> Unit
)

Material Design modal bottom sheet.

Cmn
Unit
@Composable
ModalDrawerSheet(
    modifier: Modifier,
    drawerShape: Shape,
    drawerContainerColor: Color,
    drawerContentColor: Color,
    drawerTonalElevation: Dp,
    windowInsets: WindowInsets,
    content: @Composable ColumnScope.() -> Unit
)

Content inside of a modal navigation drawer.

Cmn
Unit
@Composable
ModalDrawerSheet(
    drawerState: DrawerState,
    modifier: Modifier,
    drawerShape: Shape,
    drawerContainerColor: Color,
    drawerContentColor: Color,
    drawerTonalElevation: Dp,
    windowInsets: WindowInsets,
    content: @Composable ColumnScope.() -> Unit
)

Content inside of a modal navigation drawer.

Cmn
Unit
@Composable
ModalNavigationDrawer(
    drawerContent: @Composable () -> Unit,
    modifier: Modifier,
    drawerState: DrawerState,
    gesturesEnabled: Boolean,
    scrimColor: Color,
    content: @Composable () -> Unit
)

Material Design navigation drawer.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
ModalWideNavigationRail(
    modifier: Modifier,
    state: WideNavigationRailState,
    hideOnCollapse: Boolean,
    collapsedShape: Shape,
    expandedShape: Shape,
    colors: WideNavigationRailColors,
    header: (@Composable () -> Unit)?,
    expandedHeaderTopPadding: Dp,
    windowInsets: WindowInsets,
    arrangement: WideNavigationRailArrangement,
    expandedProperties: ModalWideNavigationRailProperties,
    content: @Composable () -> Unit
)

Material design modal wide navigation rail.

Cmn
Unit
@Composable
MultiChoiceSegmentedButtonRow(
    modifier: Modifier,
    space: Dp,
    content: @Composable MultiChoiceSegmentedButtonRowScope.() -> Unit
)

Material Segmented Button.

Cmn
Unit
@Composable
NavigationBar(
    modifier: Modifier,
    containerColor: Color,
    contentColor: Color,
    tonalElevation: Dp,
    windowInsets: WindowInsets,
    content: @Composable RowScope.() -> Unit
)

Material Design bottom navigation bar.

Cmn
Unit
@Composable
NavigationDrawerItem(
    label: @Composable () -> Unit,
    selected: Boolean,
    onClick: () -> Unit,
    modifier: Modifier,
    icon: (@Composable () -> Unit)?,
    badge: (@Composable () -> Unit)?,
    shape: Shape,
    colors: NavigationDrawerItemColors,
    interactionSource: MutableInteractionSource?
)

Material Design navigation drawer item.

Cmn
Unit
@Composable
NavigationRail(
    modifier: Modifier,
    containerColor: Color,
    contentColor: Color,
    header: (@Composable ColumnScope.() -> Unit)?,
    windowInsets: WindowInsets,
    content: @Composable ColumnScope.() -> Unit
)

Material Design bottom navigation rail.

Cmn
Unit
@Composable
NavigationRailItem(
    selected: Boolean,
    onClick: () -> Unit,
    icon: @Composable () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    label: (@Composable () -> Unit)?,
    alwaysShowLabel: Boolean,
    colors: NavigationRailItemColors,
    interactionSource: MutableInteractionSource?
)

Material Design navigation rail item.

Cmn
Unit
@Composable
OutlinedButton(
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shape: Shape,
    colors: ButtonColors,
    elevation: ButtonElevation?,
    border: BorderStroke?,
    contentPadding: PaddingValues,
    interactionSource: MutableInteractionSource?,
    content: @Composable RowScope.() -> Unit
)

Material Design outlined button.

Cmn
Unit
@Composable
OutlinedCard(
    modifier: Modifier,
    shape: Shape,
    colors: CardColors,
    elevation: CardElevation,
    border: BorderStroke,
    content: @Composable ColumnScope.() -> Unit
)

Material Design outlined card.

Cmn
Unit
@Composable
OutlinedCard(
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shape: Shape,
    colors: CardColors,
    elevation: CardElevation,
    border: BorderStroke,
    interactionSource: MutableInteractionSource?,
    content: @Composable ColumnScope.() -> Unit
)

Material Design outlined card.

Cmn
Unit
@Composable
OutlinedIconButton(
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shape: Shape,
    colors: IconButtonColors,
    border: BorderStroke?,
    interactionSource: MutableInteractionSource?,
    content: @Composable () -> Unit
)

Material Design outlined icon button.

Cmn
Unit
@Composable
OutlinedIconToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shape: Shape,
    colors: IconToggleButtonColors,
    border: BorderStroke?,
    interactionSource: MutableInteractionSource?,
    content: @Composable () -> Unit
)

Material Design outlined icon toggle button.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
OutlinedIconToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    shapes: IconButtonShapes,
    modifier: Modifier,
    enabled: Boolean,
    colors: IconToggleButtonColors,
    border: BorderStroke?,
    interactionSource: MutableInteractionSource?,
    content: @Composable () -> Unit
)

Material Design outlined icon toggle button.

Cmn
Unit
@Composable
OutlinedSecureTextField(
    state: TextFieldState,
    modifier: Modifier,
    enabled: Boolean,
    textStyle: TextStyle,
    labelPosition: TextFieldLabelPosition,
    label: (@Composable TextFieldLabelScope.() -> Unit)?,
    placeholder: (@Composable () -> Unit)?,
    leadingIcon: (@Composable () -> Unit)?,
    trailingIcon: (@Composable () -> Unit)?,
    prefix: (@Composable () -> Unit)?,
    suffix: (@Composable () -> Unit)?,
    supportingText: (@Composable () -> Unit)?,
    isError: Boolean,
    inputTransformation: InputTransformation?,
    textObfuscationMode: TextObfuscationMode,
    textObfuscationCharacter: Char,
    keyboardOptions: KeyboardOptions,
    onKeyboardAction: KeyboardActionHandler?,
    onTextLayout: (Density.(getResult: () -> TextLayoutResult?) -> Unit)?,
    shape: Shape,
    colors: TextFieldColors,
    contentPadding: PaddingValues,
    interactionSource: MutableInteractionSource?
)

Material Design outlined text field for secure content.

Cmn
Unit
@Composable
OutlinedTextField(
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    readOnly: Boolean,
    textStyle: TextStyle,
    label: (@Composable () -> Unit)?,
    placeholder: (@Composable () -> Unit)?,
    leadingIcon: (@Composable () -> Unit)?,
    trailingIcon: (@Composable () -> Unit)?,
    prefix: (@Composable () -> Unit)?,
    suffix: (@Composable () -> Unit)?,
    supportingText: (@Composable () -> Unit)?,
    isError: Boolean,
    visualTransformation: VisualTransformation,
    keyboardOptions: KeyboardOptions,
    keyboardActions: KeyboardActions,
    singleLine: Boolean,
    maxLines: Int,
    minLines: Int,
    interactionSource: MutableInteractionSource?,
    shape: Shape,
    colors: TextFieldColors
)

Material Design outlined text field.

Cmn
Unit
@Composable
OutlinedTextField(
    value: TextFieldValue,
    onValueChange: (TextFieldValue) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    readOnly: Boolean,
    textStyle: TextStyle,
    label: (@Composable () -> Unit)?,
    placeholder: (@Composable () -> Unit)?,
    leadingIcon: (@Composable () -> Unit)?,
    trailingIcon: (@Composable () -> Unit)?,
    prefix: (@Composable () -> Unit)?,
    suffix: (@Composable () -> Unit)?,
    supportingText: (@Composable () -> Unit)?,
    isError: Boolean,
    visualTransformation: VisualTransformation,
    keyboardOptions: KeyboardOptions,
    keyboardActions: KeyboardActions,
    singleLine: Boolean,
    maxLines: Int,
    minLines: Int,
    interactionSource: MutableInteractionSource?,
    shape: Shape,
    colors: TextFieldColors
)

Material Design outlined text field.

Cmn
Unit
@Composable
OutlinedTextField(
    state: TextFieldState,
    modifier: Modifier,
    enabled: Boolean,
    readOnly: Boolean,
    textStyle: TextStyle,
    labelPosition: TextFieldLabelPosition,
    label: (@Composable TextFieldLabelScope.() -> Unit)?,
    placeholder: (@Composable () -> Unit)?,
    leadingIcon: (@Composable () -> Unit)?,
    trailingIcon: (@Composable () -> Unit)?,
    prefix: (@Composable () -> Unit)?,
    suffix: (@Composable () -> Unit)?,
    supportingText: (@Composable () -> Unit)?,
    isError: Boolean,
    inputTransformation: InputTransformation?,
    outputTransformation: OutputTransformation?,
    keyboardOptions: KeyboardOptions,
    onKeyboardAction: KeyboardActionHandler?,
    lineLimits: TextFieldLineLimits,
    onTextLayout: (Density.(getResult: () -> TextLayoutResult?) -> Unit)?,
    scrollState: ScrollState,
    shape: Shape,
    colors: TextFieldColors,
    contentPadding: PaddingValues,
    interactionSource: MutableInteractionSource?
)

Material Design outlined text field.

Cmn
Unit
@Composable
@ExperimentalMaterial3ExpressiveApi
OutlinedToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shapes: ButtonShapes,
    colors: ToggleButtonColors,
    elevation: ButtonElevation?,
    border: BorderStroke?,
    contentPadding: PaddingValues,
    interactionSource: MutableInteractionSource?,
    content: @Composable RowScope.() -> Unit
)

TODO link to mio page when available.

Cmn
Unit
@Composable
PermanentDrawerSheet(
    modifier: Modifier,
    drawerShape: Shape,
    drawerContainerColor: Color,
    drawerContentColor: Color,
    drawerTonalElevation: Dp,
    windowInsets: WindowInsets,
    content: @Composable ColumnScope.() -> Unit
)

Content inside of a permanent navigation drawer.

Cmn
Unit
@Composable
PermanentNavigationDrawer(
    drawerContent: @Composable () -> Unit,
    modifier: Modifier,
    content: @Composable () -> Unit
)

Material Design navigation permanent drawer.

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
PrimaryScrollableTabRow(
    selectedTabIndex: Int,
    modifier: Modifier,
    scrollState: ScrollState,
    containerColor: Color,
    contentColor: Color,
    edgePadding: Dp,
    indicator: @Composable TabIndicatorScope.() -> Unit,
    divider: @Composable () -> Unit,
    tabs: @Composable () -> Unit
)

Material Design Scrollable Primary tabs

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
PrimaryTabRow(
    selectedTabIndex: Int,
    modifier: Modifier,
    containerColor: Color,
    contentColor: Color,
    indicator: @Composable TabIndicatorScope.() -> Unit,
    divider: @Composable () -> Unit,
    tabs: @Composable () -> Unit
)

Material Design Fixed Primary tabs

Cmn
Unit

This function is used to set the current value of LocalTextStyle, merging the given style with the current style values for any missing attributes.

Cmn
Unit
@Composable
RadioButton(
    selected: Boolean,
    onClick: (() -> Unit)?,
    modifier: Modifier,
    enabled: Boolean,
    colors: RadioButtonColors,
    interactionSource: MutableInteractionSource?
)

Material Design radio button.

Cmn
Unit
@Composable
RangeSlider(
    value: ClosedFloatingPointRange<Float>,
    onValueChange: (ClosedFloatingPointRange<Float>) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    valueRange: ClosedFloatingPointRange<Float>,
    steps: @IntRange(from = 0) Int,
    onValueChangeFinished: (() -> Unit)?,
    colors: SliderColors
)

Material Design Range slider.

Cmn
Unit
@Composable
@ExperimentalMaterial3Api
RangeSlider(
    state: RangeSliderState,
    modifier: Modifier,
    enabled: Boolean,
    colors: SliderColors,
    startInteractionSource: MutableInteractionSource,
    endInteractionSource: MutableInteractionSource,
    startThumb: @Composable (RangeSliderState) -> Unit,
    endThumb: @Composable (RangeSliderState) -> Unit,
    track: @Composable (RangeSliderState) -> Unit
)

Material Design Range slider.

Cmn
Unit
@Composable
@ExperimentalMaterial3Api
RangeSlider(
    value: ClosedFloatingPointRange<Float>,
    onValueChange: (ClosedFloatingPointRange<Float>) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    valueRange: ClosedFloatingPointRange<Float>,
    onValueChangeFinished: (() -> Unit)?,
    colors: SliderColors,
    startInteractionSource: MutableInteractionSource,
    endInteractionSource: MutableInteractionSource,
    startThumb: @Composable (RangeSliderState) -> Unit,
    endThumb: @Composable (RangeSliderState) -> Unit,
    track: @Composable (RangeSliderState) -> Unit,
    steps: @IntRange(from = 0) Int
)

Material Design Range slider.

Cmn
Unit
@Composable
Scaffold(
    modifier: Modifier,
    topBar: @Composable () -> Unit,
    bottomBar: @Composable () -> Unit,
    snackbarHost: @Composable () -> Unit,
    floatingActionButton: @Composable () -> Unit,
    floatingActionButtonPosition: FabPosition,
    containerColor: Color,
    contentColor: Color,
    contentWindowInsets: WindowInsets,
    content: @Composable (PaddingValues) -> Unit
)

Material Design layout.

Cmn
Unit
@Composable
ScrollableTabRow(
    selectedTabIndex: Int,
    modifier: Modifier,
    containerColor: Color,
    contentColor: Color,
    edgePadding: Dp,
    indicator: @Composable (tabPositions: List<TabPosition>) -> Unit,
    divider: @Composable () -> Unit,
    tabs: @Composable () -> Unit
)

Material Design tabs

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
SearchBar(
    inputField: @Composable () -> Unit,
    expanded: Boolean,
    onExpandedChange: (Boolean) -> Unit,
    modifier: Modifier,
    shape: Shape,
    colors: SearchBarColors,
    tonalElevation: Dp,
    shadowElevation: Dp,
    windowInsets: WindowInsets,
    content: @Composable ColumnScope.() -> Unit
)

Material Design search.

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
SearchBar(
    query: String,
    onQueryChange: (String) -> Unit,
    onSearch: (String) -> Unit,
    active: Boolean,
    onActiveChange: (Boolean) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    placeholder: (@Composable () -> Unit)?,
    leadingIcon: (@Composable () -> Unit)?,
    trailingIcon: (@Composable () -> Unit)?,
    shape: Shape,
    colors: SearchBarColors,
    tonalElevation: Dp,
    shadowElevation: Dp,
    windowInsets: WindowInsets,
    interactionSource: MutableInteractionSource?,
    content: @Composable ColumnScope.() -> Unit
)

This function is deprecated. Use overload which takes inputField as a parameter

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
SecondaryScrollableTabRow(
    selectedTabIndex: Int,
    modifier: Modifier,
    scrollState: ScrollState,
    containerColor: Color,
    contentColor: Color,
    edgePadding: Dp,
    indicator: @Composable TabIndicatorScope.() -> Unit,
    divider: @Composable () -> Unit,
    tabs: @Composable () -> Unit
)

Material Design Scrollable Secondary tabs

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
SecondaryTabRow(
    selectedTabIndex: Int,
    modifier: Modifier,
    containerColor: Color,
    contentColor: Color,
    indicator: @Composable TabIndicatorScope.() -> Unit,
    divider: @Composable () -> Unit,
    tabs: @Composable () -> Unit
)

Material Design Fixed Secondary tabs

Cmn
Unit
@Composable
SecureTextField(
    state: TextFieldState,
    modifier: Modifier,
    enabled: Boolean,
    textStyle: TextStyle,
    labelPosition: TextFieldLabelPosition,
    label: (@Composable TextFieldLabelScope.() -> Unit)?,
    placeholder: (@Composable () -> Unit)?,
    leadingIcon: (@Composable () -> Unit)?,
    trailingIcon: (@Composable () -> Unit)?,
    prefix: (@Composable () -> Unit)?,
    suffix: (@Composable () -> Unit)?,
    supportingText: (@Composable () -> Unit)?,
    isError: Boolean,
    inputTransformation: InputTransformation?,
    textObfuscationMode: TextObfuscationMode,
    textObfuscationCharacter: Char,
    keyboardOptions: KeyboardOptions,
    onKeyboardAction: KeyboardActionHandler?,
    onTextLayout: (Density.(getResult: () -> TextLayoutResult?) -> Unit)?,
    shape: Shape,
    colors: TextFieldColors,
    contentPadding: PaddingValues,
    interactionSource: MutableInteractionSource?
)

Material Design filled text field for secure content.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
ShortNavigationBar(
    modifier: Modifier,
    containerColor: Color,
    contentColor: Color,
    windowInsets: WindowInsets,
    arrangement: ShortNavigationBarArrangement,
    content: @Composable () -> Unit
)

Material Design short navigation bar.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
ShortNavigationBarItem(
    selected: Boolean,
    onClick: () -> Unit,
    icon: @Composable () -> Unit,
    label: (@Composable () -> Unit)?,
    modifier: Modifier,
    enabled: Boolean,
    iconPosition: NavigationItemIconPosition,
    colors: NavigationItemColors,
    interactionSource: MutableInteractionSource?
)

Material Design short navigation bar item.

Cmn
Unit
@Composable
SingleChoiceSegmentedButtonRow(
    modifier: Modifier,
    space: Dp,
    content: @Composable SingleChoiceSegmentedButtonRowScope.() -> Unit
)

Material Segmented Button.

Cmn
Unit
@Composable
@ExperimentalMaterial3Api
Slider(
    state: SliderState,
    modifier: Modifier,
    enabled: Boolean,
    colors: SliderColors,
    interactionSource: MutableInteractionSource,
    thumb: @Composable (SliderState) -> Unit,
    track: @Composable (SliderState) -> Unit
)

Material Design slider.

Cmn
Unit
@Composable
Slider(
    value: Float,
    onValueChange: (Float) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    valueRange: ClosedFloatingPointRange<Float>,
    steps: @IntRange(from = 0) Int,
    onValueChangeFinished: (() -> Unit)?,
    colors: SliderColors,
    interactionSource: MutableInteractionSource
)

Material Design slider.

Cmn
Unit
@Composable
@ExperimentalMaterial3Api
Slider(
    value: Float,
    onValueChange: (Float) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    onValueChangeFinished: (() -> Unit)?,
    colors: SliderColors,
    interactionSource: MutableInteractionSource,
    steps: @IntRange(from = 0) Int,
    thumb: @Composable (SliderState) -> Unit,
    track: @Composable (SliderState) -> Unit,
    valueRange: ClosedFloatingPointRange<Float>
)

Material Design slider.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
SmallExtendedFloatingActionButton(
    onClick: () -> Unit,
    modifier: Modifier,
    shape: Shape,
    containerColor: Color,
    contentColor: Color,
    elevation: FloatingActionButtonElevation,
    interactionSource: MutableInteractionSource?,
    content: @Composable RowScope.() -> Unit
)

Material Design small extended floating action button.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
SmallExtendedFloatingActionButton(
    text: @Composable () -> Unit,
    icon: @Composable () -> Unit,
    onClick: () -> Unit,
    modifier: Modifier,
    expanded: Boolean,
    shape: Shape,
    containerColor: Color,
    contentColor: Color,
    elevation: FloatingActionButtonElevation,
    interactionSource: MutableInteractionSource?
)

Material Design small extended floating action button.

Cmn
Unit
@Composable
SmallFloatingActionButton(
    onClick: () -> Unit,
    modifier: Modifier,
    shape: Shape,
    containerColor: Color,
    contentColor: Color,
    elevation: FloatingActionButtonElevation,
    interactionSource: MutableInteractionSource?,
    content: @Composable () -> Unit
)

Material Design small floating action button.

Cmn
Unit
@Composable
Snackbar(
    snackbarData: SnackbarData,
    modifier: Modifier,
    actionOnNewLine: Boolean,
    shape: Shape,
    containerColor: Color,
    contentColor: Color,
    actionColor: Color,
    actionContentColor: Color,
    dismissActionContentColor: Color
)

Material Design snackbar.

Cmn
Unit
@Composable
Snackbar(
    modifier: Modifier,
    action: (@Composable () -> Unit)?,
    dismissAction: (@Composable () -> Unit)?,
    actionOnNewLine: Boolean,
    shape: Shape,
    containerColor: Color,
    contentColor: Color,
    actionContentColor: Color,
    dismissActionContentColor: Color,
    content: @Composable () -> Unit
)

Material Design snackbar.

Cmn
Unit
@Composable
SnackbarHost(
    hostState: SnackbarHostState,
    modifier: Modifier,
    snackbar: @Composable (SnackbarData) -> Unit
)

Host for Snackbars to be used in Scaffold to properly show, hide and dismiss items based on Material specification and the hostState.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
SplitButtonLayout(
    leadingButton: @Composable () -> Unit,
    trailingButton: @Composable () -> Unit,
    modifier: Modifier,
    spacing: Dp
)

A SplitButtonLayout let user define a button group consisting of 2 buttons.

Cmn
Unit
@Composable
SuggestionChip(
    onClick: () -> Unit,
    label: @Composable () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    icon: (@Composable () -> Unit)?,
    shape: Shape,
    colors: ChipColors,
    elevation: ChipElevation?,
    border: BorderStroke?,
    interactionSource: MutableInteractionSource?
)

Material Design suggestion chip.

Cmn
Unit
@Composable
@NonRestartableComposable
Surface(
    modifier: Modifier,
    shape: Shape,
    color: Color,
    contentColor: Color,
    tonalElevation: Dp,
    shadowElevation: Dp,
    border: BorderStroke?,
    content: @Composable () -> Unit
)

Material surface is the central metaphor in material design.

Cmn
Unit
@Composable
@NonRestartableComposable
Surface(
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shape: Shape,
    color: Color,
    contentColor: Color,
    tonalElevation: Dp,
    shadowElevation: Dp,
    border: BorderStroke?,
    interactionSource: MutableInteractionSource?,
    content: @Composable () -> Unit
)

Material surface is the central metaphor in material design.

Cmn
Unit
@Composable
@NonRestartableComposable
Surface(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shape: Shape,
    color: Color,
    contentColor: Color,
    tonalElevation: Dp,
    shadowElevation: Dp,
    border: BorderStroke?,
    interactionSource: MutableInteractionSource?,
    content: @Composable () -> Unit
)

Material surface is the central metaphor in material design.

Cmn
Unit
@Composable
@NonRestartableComposable
Surface(
    selected: Boolean,
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shape: Shape,
    color: Color,
    contentColor: Color,
    tonalElevation: Dp,
    shadowElevation: Dp,
    border: BorderStroke?,
    interactionSource: MutableInteractionSource?,
    content: @Composable () -> Unit
)

Material surface is the central metaphor in material design.

Cmn
Unit
@Composable
SwipeToDismissBox(
    state: SwipeToDismissBoxState,
    backgroundContent: @Composable RowScope.() -> Unit,
    modifier: Modifier,
    enableDismissFromStartToEnd: Boolean,
    enableDismissFromEndToStart: Boolean,
    gesturesEnabled: Boolean,
    content: @Composable RowScope.() -> Unit
)

A composable that can be dismissed by swiping left or right.

Cmn
Unit
@Composable
Switch(
    checked: Boolean,
    onCheckedChange: ((Boolean) -> Unit)?,
    modifier: Modifier,
    thumbContent: (@Composable () -> Unit)?,
    enabled: Boolean,
    colors: SwitchColors,
    interactionSource: MutableInteractionSource?
)

Material Design Switch.

Cmn
Unit
@Composable
Tab(
    selected: Boolean,
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    selectedContentColor: Color,
    unselectedContentColor: Color,
    interactionSource: MutableInteractionSource?,
    content: @Composable ColumnScope.() -> Unit
)

Material Design tab.

Cmn
Unit
@Composable
Tab(
    selected: Boolean,
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    text: (@Composable () -> Unit)?,
    icon: (@Composable () -> Unit)?,
    selectedContentColor: Color,
    unselectedContentColor: Color,
    interactionSource: MutableInteractionSource?
)

Material Design tab.

Cmn
Unit
@Composable
TabRow(
    selectedTabIndex: Int,
    modifier: Modifier,
    containerColor: Color,
    contentColor: Color,
    indicator: @Composable (tabPositions: List<TabPosition>) -> Unit,
    divider: @Composable () -> Unit,
    tabs: @Composable () -> Unit
)

Material Design tabs

Cmn
Unit
@Composable
Text(
    text: String,
    modifier: Modifier,
    color: Color,
    fontSize: TextUnit,
    fontStyle: FontStyle?,
    fontWeight: FontWeight?,
    fontFamily: FontFamily?,
    letterSpacing: TextUnit,
    textDecoration: TextDecoration?,
    textAlign: TextAlign?,
    lineHeight: TextUnit,
    overflow: TextOverflow,
    softWrap: Boolean,
    maxLines: Int,
    minLines: Int,
    onTextLayout: ((TextLayoutResult) -> Unit)?,
    style: TextStyle
)

High level element that displays text and provides semantics / accessibility information.

Cmn
Unit
@Composable
Text(
    text: AnnotatedString,
    modifier: Modifier,
    color: Color,
    fontSize: TextUnit,
    fontStyle: FontStyle?,
    fontWeight: FontWeight?,
    fontFamily: FontFamily?,
    letterSpacing: TextUnit,
    textDecoration: TextDecoration?,
    textAlign: TextAlign?,
    lineHeight: TextUnit,
    overflow: TextOverflow,
    softWrap: Boolean,
    maxLines: Int,
    minLines: Int,
    inlineContent: Map<StringInlineTextContent>,
    onTextLayout: (TextLayoutResult) -> Unit,
    style: TextStyle
)

High level element that displays text and provides semantics / accessibility information.

Cmn
Unit
@Composable
TextButton(
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shape: Shape,
    colors: ButtonColors,
    elevation: ButtonElevation?,
    border: BorderStroke?,
    contentPadding: PaddingValues,
    interactionSource: MutableInteractionSource?,
    content: @Composable RowScope.() -> Unit
)

Material Design text button.

Cmn
Unit
@Composable
TextField(
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    readOnly: Boolean,
    textStyle: TextStyle,
    label: (@Composable () -> Unit)?,
    placeholder: (@Composable () -> Unit)?,
    leadingIcon: (@Composable () -> Unit)?,
    trailingIcon: (@Composable () -> Unit)?,
    prefix: (@Composable () -> Unit)?,
    suffix: (@Composable () -> Unit)?,
    supportingText: (@Composable () -> Unit)?,
    isError: Boolean,
    visualTransformation: VisualTransformation,
    keyboardOptions: KeyboardOptions,
    keyboardActions: KeyboardActions,
    singleLine: Boolean,
    maxLines: Int,
    minLines: Int,
    interactionSource: MutableInteractionSource?,
    shape: Shape,
    colors: TextFieldColors
)

Material Design filled text field.

Cmn
Unit
@Composable
TextField(
    value: TextFieldValue,
    onValueChange: (TextFieldValue) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    readOnly: Boolean,
    textStyle: TextStyle,
    label: (@Composable () -> Unit)?,
    placeholder: (@Composable () -> Unit)?,
    leadingIcon: (@Composable () -> Unit)?,
    trailingIcon: (@Composable () -> Unit)?,
    prefix: (@Composable () -> Unit)?,
    suffix: (@Composable () -> Unit)?,
    supportingText: (@Composable () -> Unit)?,
    isError: Boolean,
    visualTransformation: VisualTransformation,
    keyboardOptions: KeyboardOptions,
    keyboardActions: KeyboardActions,
    singleLine: Boolean,
    maxLines: Int,
    minLines: Int,
    interactionSource: MutableInteractionSource?,
    shape: Shape,
    colors: TextFieldColors
)

Material Design filled text field.

Cmn
Unit
@Composable
TextField(
    state: TextFieldState,
    modifier: Modifier,
    enabled: Boolean,
    readOnly: Boolean,
    textStyle: TextStyle,
    labelPosition: TextFieldLabelPosition,
    label: (@Composable TextFieldLabelScope.() -> Unit)?,
    placeholder: (@Composable () -> Unit)?,
    leadingIcon: (@Composable () -> Unit)?,
    trailingIcon: (@Composable () -> Unit)?,
    prefix: (@Composable () -> Unit)?,
    suffix: (@Composable () -> Unit)?,
    supportingText: (@Composable () -> Unit)?,
    isError: Boolean,
    inputTransformation: InputTransformation?,
    outputTransformation: OutputTransformation?,
    keyboardOptions: KeyboardOptions,
    onKeyboardAction: KeyboardActionHandler?,
    lineLimits: TextFieldLineLimits,
    onTextLayout: (Density.(getResult: () -> TextLayoutResult?) -> Unit)?,
    scrollState: ScrollState,
    shape: Shape,
    colors: TextFieldColors,
    contentPadding: PaddingValues,
    interactionSource: MutableInteractionSource?
)

Material Design filled text field.

Cmn
Unit
@Composable
@ExperimentalMaterial3Api
TimeInput(
    state: TimePickerState,
    modifier: Modifier,
    colors: TimePickerColors
)

Time pickers help users select and set a specific time.

Cmn
Unit
@Composable
@ExperimentalMaterial3Api
TimePicker(
    state: TimePickerState,
    modifier: Modifier,
    colors: TimePickerColors,
    layoutType: TimePickerLayoutType
)

Material Design time picker.

Cmn
TimePickerState
@ExperimentalMaterial3Api
TimePickerState(initialHour: Int, initialMinute: Int, is24Hour: Boolean)

Factory function for the default implementation of TimePickerState should be used in most cases.

Cmn
Unit
@Composable
@ExperimentalMaterial3ExpressiveApi
ToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shapes: ButtonShapes,
    colors: ToggleButtonColors,
    elevation: ButtonElevation?,
    border: BorderStroke?,
    contentPadding: PaddingValues,
    interactionSource: MutableInteractionSource?,
    content: @Composable RowScope.() -> Unit
)

TODO link to mio page when available.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
ToggleFloatingActionButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier,
    containerColor: (Float) -> Color,
    contentAlignment: Alignment,
    containerSize: (Float) -> Dp,
    containerCornerRadius: (Float) -> Dp,
    content: @Composable ToggleFloatingActionButtonScope.() -> Unit
)

Toggleable FAB supports animating its container size, corner radius, and color when it is toggled, and should be used in conjunction with a FloatingActionButtonMenu to provide additional choices to the user after clicking the FAB.

Cmn
Unit
@Composable
@ExperimentalMaterial3ExpressiveApi
TonalToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    shapes: ButtonShapes,
    colors: ToggleButtonColors,
    elevation: ButtonElevation?,
    border: BorderStroke?,
    contentPadding: PaddingValues,
    interactionSource: MutableInteractionSource?,
    content: @Composable RowScope.() -> Unit
)

TODO link to mio page when available.

Cmn
Unit
@Composable
@ExperimentalMaterial3Api
TooltipBox(
    positionProvider: PopupPositionProvider,
    tooltip: @Composable TooltipScope.() -> Unit,
    state: TooltipState,
    modifier: Modifier,
    onDismissRequest: (() -> Unit)?,
    focusable: Boolean,
    enableUserInput: Boolean,
    content: @Composable () -> Unit
)

Material TooltipBox that wraps a composable with a tooltip.

Cmn
TooltipState
@ExperimentalMaterial3Api
TooltipState(
    initialIsVisible: Boolean,
    isPersistent: Boolean,
    mutatorMutex: MutatorMutex
)

Constructor extension function for TooltipState

Cmn
Unit
@ExperimentalMaterial3Api
@Composable
TopAppBar(
    title: @Composable () -> Unit,
    modifier: Modifier,
    navigationIcon: @Composable () -> Unit,
    actions: @Composable RowScope.() -> Unit,
    expandedHeight: Dp,
    windowInsets: WindowInsets,
    colors: TopAppBarColors,
    scrollBehavior: TopAppBarScrollBehavior?
)

Material Design small top app bar.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
TopAppBar(
    title: @Composable () -> Unit,
    subtitle: @Composable () -> Unit,
    modifier: Modifier,
    navigationIcon: @Composable () -> Unit,
    actions: @Composable RowScope.() -> Unit,
    titleHorizontalAlignment: TopAppBarTitleAlignment,
    expandedHeight: Dp,
    windowInsets: WindowInsets,
    colors: TopAppBarColors,
    scrollBehavior: TopAppBarScrollBehavior?
)

Material Design small top app bar.

Cmn
Unit
@Composable
TriStateCheckbox(
    state: ToggleableState,
    onClick: (() -> Unit)?,
    modifier: Modifier,
    enabled: Boolean,
    colors: CheckboxColors,
    interactionSource: MutableInteractionSource?
)

Material Design checkbox parent.

Cmn
Unit
@Composable
VerticalDivider(modifier: Modifier, thickness: Dp, color: Color)

Material Design divider.

Cmn
Unit
@Composable
VerticalDragHandle(
    modifier: Modifier,
    sizes: DragHandleSizes,
    colors: DragHandleColors,
    shapes: DragHandleShapes,
    interactionSource: MutableInteractionSource?
)

Material Design Drag Handle.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
VerticalFloatingAppBar(
    expanded: Boolean,
    modifier: Modifier,
    containerColor: Color,
    contentPadding: PaddingValues,
    scrollBehavior: FloatingAppBarScrollBehavior?,
    shape: Shape,
    leadingContent: (@Composable ColumnScope.() -> Unit)?,
    trailingContent: (@Composable ColumnScope.() -> Unit)?,
    content: @Composable ColumnScope.() -> Unit
)
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.FloatingAppBarDefaults.ScreenOffset
import androidx.compose.material3.FloatingAppBarExitDirection.Companion.End
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.VerticalFloatingAppBar
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment.Companion.CenterEnd
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp

val context = LocalContext.current
val isTouchExplorationEnabled = remember {
    val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
    am.isEnabled && am.isTouchExplorationEnabled
}
val listState = rememberLazyListState()
var currentItem = 0
val expanded by remember {
    derivedStateOf {
        val temp = currentItem
        currentItem = listState.firstVisibleItemIndex
        listState.firstVisibleItemIndex <= temp // true if the list is scrolled up
    }
}
Scaffold(
    content = { innerPadding ->
        Box {
            LazyColumn(
                state = listState,
                contentPadding = innerPadding,
                verticalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                val list = (0..75).map { it.toString() }
                items(count = list.size) {
                    Text(
                        text = list[it],
                        style = MaterialTheme.typography.bodyLarge,
                        modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                    )
                }
            }
            VerticalFloatingAppBar(
                modifier = Modifier.align(CenterEnd).offset(x = -ScreenOffset),
                expanded = expanded || isTouchExplorationEnabled,
                leadingContent = { leadingContent() },
                trailingContent = { trailingContent() },
                content = {
                    FilledIconButton(
                        modifier = Modifier.height(64.dp),
                        onClick = { /* doSomething() */ }
                    ) {
                        Icon(Icons.Filled.Add, contentDescription = "Localized description")
                    }
                },
            )
        }
    }
)
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.FloatingAppBarDefaults
import androidx.compose.material3.FloatingAppBarDefaults.ScreenOffset
import androidx.compose.material3.FloatingAppBarExitDirection.Companion.End
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.VerticalFloatingAppBar
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment.Companion.CenterEnd
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp

val context = LocalContext.current
val isTouchExplorationEnabled = remember {
    val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
    am.isEnabled && am.isTouchExplorationEnabled
}
val listState = rememberLazyListState()
val exitAlwaysScrollBehavior =
    FloatingAppBarDefaults.exitAlwaysScrollBehavior(exitDirection = End)
Scaffold(
    modifier = Modifier.nestedScroll(exitAlwaysScrollBehavior),
    content = { innerPadding ->
        Box {
            LazyColumn(
                state = listState,
                contentPadding = innerPadding,
                verticalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                val list = (0..75).map { it.toString() }
                items(count = list.size) {
                    Text(
                        text = list[it],
                        style = MaterialTheme.typography.bodyLarge,
                        modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                    )
                }
            }
            VerticalFloatingAppBar(
                modifier = Modifier.align(CenterEnd).offset(x = -ScreenOffset),
                expanded = true,
                leadingContent = { leadingContent() },
                trailingContent = { trailingContent() },
                content = {
                    FilledIconButton(
                        modifier = Modifier.height(64.dp),
                        onClick = { /* doSomething() */ }
                    ) {
                        Icon(Icons.Filled.Add, contentDescription = "Localized description")
                    }
                },
                scrollBehavior =
                    if (!isTouchExplorationEnabled) exitAlwaysScrollBehavior else null,
            )
        }
    }
)
Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
WideNavigationRail(
    modifier: Modifier,
    state: WideNavigationRailState,
    shape: Shape,
    colors: WideNavigationRailColors,
    header: (@Composable () -> Unit)?,
    windowInsets: WindowInsets,
    arrangement: WideNavigationRailArrangement,
    content: @Composable () -> Unit
)

Material design wide navigation rail.

Cmn
Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
WideNavigationRailItem(
    selected: Boolean,
    onClick: () -> Unit,
    icon: @Composable () -> Unit,
    label: (@Composable () -> Unit)?,
    modifier: Modifier,
    enabled: Boolean,
    railExpanded: Boolean,
    iconPosition: NavigationItemIconPosition,
    colors: NavigationItemColors,
    interactionSource: MutableInteractionSource?
)

Material Design wide navigation rail item.

Cmn
Color
@Composable
contentColorFor(backgroundColor: Color)

The Material color system contains pairs of colors that are typically used for the background and content color inside a component.

Cmn
ColorScheme
darkColorScheme(
    primary: Color,
    onPrimary: Color,
    primaryContainer: Color,
    onPrimaryContainer: Color,
    inversePrimary: Color,
    secondary: Color,
    onSecondary: Color,
    secondaryContainer: Color,
    onSecondaryContainer: Color,
    tertiary: Color,
    onTertiary: Color,
    tertiaryContainer: Color,
    onTertiaryContainer: Color,
    background: Color,
    onBackground: Color,
    surface: Color,
    onSurface: Color,
    surfaceVariant: Color,
    onSurfaceVariant: Color,
    surfaceTint: Color,
    inverseSurface: Color,
    inverseOnSurface: Color,
    error: Color,
    onError: Color,
    errorContainer: Color,
    onErrorContainer: Color,
    outline: Color,
    outlineVariant: Color,
    scrim: Color,
    surfaceBright: Color,
    surfaceContainer: Color,
    surfaceContainerHigh: Color,
    surfaceContainerHighest: Color,
    surfaceContainerLow: Color,
    surfaceContainerLowest: Color,
    surfaceDim: Color
)

Returns a dark Material color scheme.

Cmn
ColorScheme
@RequiresApi(value = 31)
dynamicDarkColorScheme(context: Context)

Creates a dark dynamic color scheme.

android
ColorScheme

Creates a light dynamic color scheme.

android
ColorScheme

Returns a light Material color scheme.

Cmn
ColorScheme
lightColorScheme(
    primary: Color,
    onPrimary: Color,
    primaryContainer: Color,
    onPrimaryContainer: Color,
    inversePrimary: Color,
    secondary: Color,
    onSecondary: Color,
    secondaryContainer: Color,
    onSecondaryContainer: Color,
    tertiary: Color,
    onTertiary: Color,
    tertiaryContainer: Color,
    onTertiaryContainer: Color,
    background: Color,
    onBackground: Color,
    surface: Color,
    onSurface: Color,
    surfaceVariant: Color,
    onSurfaceVariant: Color,
    surfaceTint: Color,
    inverseSurface: Color,
    inverseOnSurface: Color,
    error: Color,
    onError: Color,
    errorContainer: Color,
    onErrorContainer: Color,
    outline: Color,
    outlineVariant: Color,
    scrim: Color,
    surfaceBright: Color,
    surfaceContainer: Color,
    surfaceContainerHigh: Color,
    surfaceContainerHighest: Color,
    surfaceContainerLow: Color,
    surfaceContainerLowest: Color,
    surfaceDim: Color
)

Returns a light Material color scheme.

Cmn
BottomAppBarState
@ExperimentalMaterial3Api
@Composable
rememberBottomAppBarState(
    initialHeightOffsetLimit: Float,
    initialHeightOffset: Float,
    initialContentOffset: Float
)

Creates a BottomAppBarState that is remembered across compositions.

Cmn
BottomSheetScaffoldState

Create and remember a BottomSheetScaffoldState.

Cmn
DatePickerState
@Composable
@ExperimentalMaterial3Api
rememberDatePickerState(
    initialSelectedDateMillis: Long?,
    initialDisplayedMonthMillis: Long?,
    yearRange: IntRange,
    initialDisplayMode: DisplayMode,
    selectableDates: SelectableDates
)

Creates a DatePickerState for a DatePicker that is remembered across compositions.

Cmn
DateRangePickerState
@Composable
@ExperimentalMaterial3Api
rememberDateRangePickerState(
    initialSelectedStartDateMillis: Long?,
    initialSelectedEndDateMillis: Long?,
    initialDisplayedMonthMillis: Long?,
    yearRange: IntRange,
    initialDisplayMode: DisplayMode,
    selectableDates: SelectableDates
)

Creates a DateRangePickerState for a DateRangePicker that is remembered across compositions.

Cmn
DrawerState
@Composable
rememberDrawerState(
    initialValue: DrawerValue,
    confirmStateChange: (DrawerValue) -> Boolean
)

Create and remember a DrawerState.

Cmn
FloatingAppBarState
@ExperimentalMaterial3ExpressiveApi
@Composable
rememberFloatingAppBarState(
    initialOffsetLimit: Float,
    initialOffset: Float,
    initialContentOffset: Float
)

Creates a FloatingAppBarState that is remembered across compositions.

Cmn
SheetState
@Composable
@ExperimentalMaterial3Api
rememberModalBottomSheetState(
    skipPartiallyExpanded: Boolean,
    confirmValueChange: (SheetValue) -> Boolean
)

Create and remember a SheetState for ModalBottomSheet.

Cmn
SheetState
@Composable
@ExperimentalMaterial3Api
rememberStandardBottomSheetState(
    initialValue: SheetValue,
    confirmValueChange: (SheetValue) -> Boolean,
    skipHiddenState: Boolean
)

Create and remember a SheetState for BottomSheetScaffold.

Cmn
SwipeToDismissBoxState
@Composable
rememberSwipeToDismissBoxState(
    initialValue: SwipeToDismissBoxValue,
    confirmValueChange: (SwipeToDismissBoxValue) -> Boolean,
    positionalThreshold: (totalDistance: Float) -> Float
)

Create and remember a SwipeToDismissBoxState.

Cmn
TimePickerState
@Composable
@ExperimentalMaterial3Api
rememberTimePickerState(
    initialHour: Int,
    initialMinute: Int,
    is24Hour: Boolean
)

Creates a TimePickerState for a time picker that is remembered across compositions and configuration changes.

Cmn
TooltipState
@Composable
@ExperimentalMaterial3Api
rememberTooltipState(
    initialIsVisible: Boolean,
    isPersistent: Boolean,
    mutatorMutex: MutatorMutex
)

Create and remember the default TooltipState for TooltipBox.

Cmn
TopAppBarState
@ExperimentalMaterial3Api
@Composable
rememberTopAppBarState(
    initialHeightOffsetLimit: Float,
    initialHeightOffset: Float,
    initialContentOffset: Float
)

Creates a TopAppBarState that is remembered across compositions.

Cmn
WideNavigationRailState

Create and remember a WideNavigationRailState.

Cmn
IndicationNodeFactory
ripple(bounded: Boolean, radius: Dp, color: Color)

Creates a Ripple using the provided values and values inferred from the theme.

Cmn
IndicationNodeFactory
ripple(color: ColorProducer, bounded: Boolean, radius: Dp)

Creates a Ripple using the provided values and values inferred from the theme.

Cmn

Extension functions summary

Unit
@ExperimentalMaterial3ExpressiveApi
@Composable
FloatingActionButtonMenuScope.FloatingActionButtonMenuItem(
    onClick: () -> Unit,
    text: @Composable () -> Unit,
    icon: @Composable () -> Unit,
    modifier: Modifier,
    containerColor: Color,
    contentColor: Color
)

FAB Menu Items should be used within a FloatingActionButtonMenu to provide additional choices to the user after clicking a FAB.

Cmn
Unit
@Composable
RowScope.NavigationBarItem(
    selected: Boolean,
    onClick: () -> Unit,
    icon: @Composable () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    label: (@Composable () -> Unit)?,
    alwaysShowLabel: Boolean,
    colors: NavigationBarItemColors,
    interactionSource: MutableInteractionSource?
)

Material Design navigation bar item.

Cmn
Unit
@Composable
@ExperimentalMaterial3Api
TooltipScope.PlainTooltip(
    modifier: Modifier,
    caretSize: DpSize,
    maxWidth: Dp,
    shape: Shape,
    contentColor: Color,
    containerColor: Color,
    tonalElevation: Dp,
    shadowElevation: Dp,
    content: @Composable () -> Unit
)

Plain tooltip that provides a descriptive message.

Cmn
android
Unit
@Composable
@ExperimentalMaterial3Api
TooltipScope.RichTooltip(
    modifier: Modifier,
    title: (@Composable () -> Unit)?,
    action: (@Composable () -> Unit)?,
    caretSize: DpSize,
    maxWidth: Dp,
    shape: Shape,
    colors: RichTooltipColors,
    tonalElevation: Dp,
    shadowElevation: Dp,
    text: @Composable () -> Unit
)

Rich text tooltip that allows the user to pass in a title, text, and action.

Cmn
android
Unit
@Composable
MultiChoiceSegmentedButtonRowScope.SegmentedButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    shape: Shape,
    modifier: Modifier,
    enabled: Boolean,
    colors: SegmentedButtonColors,
    border: BorderStroke,
    contentPadding: PaddingValues,
    interactionSource: MutableInteractionSource?,
    icon: @Composable () -> Unit,
    label: @Composable () -> Unit
)

Material Segmented Button.

Cmn
Unit
@Composable
SingleChoiceSegmentedButtonRowScope.SegmentedButton(
    selected: Boolean,
    onClick: () -> Unit,
    shape: Shape,
    modifier: Modifier,
    enabled: Boolean,
    colors: SegmentedButtonColors,
    border: BorderStroke,
    contentPadding: PaddingValues,
    interactionSource: MutableInteractionSource?,
    icon: @Composable () -> Unit,
    label: @Composable () -> Unit
)

Material Segmented Button.

Cmn
Modifier
@ExperimentalMaterial3ExpressiveApi
Modifier.animateFloatingActionButton(
    visible: Boolean,
    alignment: Alignment,
    targetScale: Float,
    scaleAnimationSpec: AnimationSpec<Float>?,
    alphaAnimationSpec: AnimationSpec<Float>?
)

Apply this modifier to a FloatingActionButton to show or hide it with an animation, typically based on the app's main content scrolling.

Cmn
Color
ColorScheme.contentColorFor(backgroundColor: Color)

The Material color system contains pairs of colors that are typically used for the background and content color inside a component.

Cmn
Modifier

Reserves at least 48.dp in size to disambiguate touch interactions if the element would measure smaller.

Cmn
Color

Computes the surface tonal color at different elevation levels e.g. surface1 through surface5.

Cmn
Path

Returns a Path that is remembered across compositions for this RoundedPolygon.

Cmn
Path
@ExperimentalMaterial3ExpressiveApi
Morph.toPath(progress: Float, path: Path, startAngle: Int)

Returns a Path for this Morph.

Cmn
Shape

Returns a Shape that is remembered across compositions for this RoundedPolygon.

Cmn

Top-level properties summary

ProvidableCompositionLocal<Dp>

CompositionLocal containing the current absolute elevation provided by Surface components.

Cmn
ProvidableCompositionLocal<Color>

CompositionLocal containing the preferred content color for a given position in the hierarchy.

Cmn
ProvidableCompositionLocal<Boolean>

This property is deprecated. Use LocalMinimumInteractiveComponentSize with 0.dp to turn off enforcement instead.

Cmn
ProvidableCompositionLocal<Dp>

CompositionLocal that configures the minimum touch target size for Material components (such as Button) to ensure they are accessible.

Cmn
ProvidableCompositionLocal<NavigationBarComponentOverride>

CompositionLocal containing the currently-selected NavigationBarComponentOverride.

Cmn
ProvidableCompositionLocal<NavigationRailComponentOverride>

CompositionLocal containing the currently-selected NavigationRailComponentOverride.

Cmn
ProvidableCompositionLocal<RippleConfiguration?>

CompositionLocal used for providing RippleConfiguration down the tree.

Cmn
ProvidableCompositionLocal<TextStyle>

CompositionLocal containing the preferred TextStyle that will be used by Text components by default.

Cmn
ProvidableCompositionLocal<Boolean>

Composition Local used to check if ColorScheme.applyTonalElevation will be applied down the tree.

Cmn

Extension properties summary

Boolean

Indicates whether the selected time falls within the period from 12 PM inclusive to 12 AM non inclusive.

Cmn

Top-level functions

AlertDialog

@ExperimentalMaterial3Api
@Composable
fun AlertDialog(
    onDismissRequest: () -> Unit,
    modifier: Modifier = Modifier,
    properties: DialogProperties = DialogProperties(),
    content: @Composable () -> Unit
): Unit

Basic alert dialog dialog.

Dialogs provide important prompts in a user flow. They can require an action, communicate information, or help users accomplish a task.

Basic dialog image

This basic alert dialog expects an arbitrary content that is defined by the caller. Note that your content will need to define its own styling.

By default, the displayed dialog has the minimum height and width that the Material Design spec defines. If required, these constraints can be overwritten by providing a width or height Modifiers.

Basic alert dialog usage with custom content:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.AlertDialogDefaults
import androidx.compose.material3.BasicAlertDialog
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val openDialog = remember { mutableStateOf(true) }

if (openDialog.value) {
    BasicAlertDialog(
        onDismissRequest = {
            // Dismiss the dialog when the user clicks outside the dialog or on the back
            // button. If you want to disable that functionality, simply use an empty
            // onDismissRequest.
            openDialog.value = false
        }
    ) {
        Surface(
            modifier = Modifier.wrapContentWidth().wrapContentHeight(),
            shape = MaterialTheme.shapes.large,
            tonalElevation = AlertDialogDefaults.TonalElevation
        ) {
            Column(modifier = Modifier.padding(16.dp)) {
                Text(
                    text =
                        "This area typically contains the supportive text " +
                            "which presents the details regarding the Dialog's purpose.",
                )
                Spacer(modifier = Modifier.height(24.dp))
                TextButton(
                    onClick = { openDialog.value = false },
                    modifier = Modifier.align(Alignment.End)
                ) {
                    Text("Confirm")
                }
            }
        }
    }
}
Parameters
onDismissRequest: () -> Unit

called when the user tries to dismiss the Dialog by clicking outside or pressing the back button. This is not called when the dismiss button is clicked.

modifier: Modifier = Modifier

the Modifier to be applied to this dialog's content.

properties: DialogProperties = DialogProperties()

typically platform specific properties to further configure the dialog.

content: @Composable () -> Unit

the content of the dialog

AlertDialog

@Composable
fun AlertDialog(
    onDismissRequest: () -> Unit,
    confirmButton: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    dismissButton: (@Composable () -> Unit)? = null,
    icon: (@Composable () -> Unit)? = null,
    title: (@Composable () -> Unit)? = null,
    text: (@Composable () -> Unit)? = null,
    shape: Shape = AlertDialogDefaults.shape,
    containerColor: Color = AlertDialogDefaults.containerColor,
    iconContentColor: Color = AlertDialogDefaults.iconContentColor,
    titleContentColor: Color = AlertDialogDefaults.titleContentColor,
    textContentColor: Color = AlertDialogDefaults.textContentColor,
    tonalElevation: Dp = AlertDialogDefaults.TonalElevation,
    properties: DialogProperties = DialogProperties()
): Unit

Material Design basic dialog.

Dialogs provide important prompts in a user flow. They can require an action, communicate information, or help users accomplish a task.

Basic dialog image

The dialog will position its buttons, typically TextButtons, based on the available space. By default it will try to place them horizontally next to each other and fallback to horizontal placement if not enough space is available.

Simple usage:

import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

val openDialog = remember { mutableStateOf(true) }

if (openDialog.value) {
    AlertDialog(
        onDismissRequest = {
            // Dismiss the dialog when the user clicks outside the dialog or on the back
            // button. If you want to disable that functionality, simply use an empty
            // onDismissRequest.
            openDialog.value = false
        },
        title = { Text(text = "Title") },
        text = { Text(text = "Turned on by default") },
        confirmButton = {
            TextButton(onClick = { openDialog.value = false }) { Text("Confirm") }
        },
        dismissButton = {
            TextButton(onClick = { openDialog.value = false }) { Text("Dismiss") }
        }
    )
}

Usage with a "Hero" icon:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

val openDialog = remember { mutableStateOf(true) }

if (openDialog.value) {
    AlertDialog(
        onDismissRequest = {
            // Dismiss the dialog when the user clicks outside the dialog or on the back
            // button. If you want to disable that functionality, simply use an empty
            // onDismissRequest.
            openDialog.value = false
        },
        icon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
        title = { Text(text = "Title") },
        text = {
            Text(
                "This area typically contains the supportive text " +
                    "which presents the details regarding the Dialog's purpose."
            )
        },
        confirmButton = {
            TextButton(onClick = { openDialog.value = false }) { Text("Confirm") }
        },
        dismissButton = {
            TextButton(onClick = { openDialog.value = false }) { Text("Dismiss") }
        }
    )
}
Parameters
onDismissRequest: () -> Unit

called when the user tries to dismiss the Dialog by clicking outside or pressing the back button. This is not called when the dismiss button is clicked.

confirmButton: @Composable () -> Unit

button which is meant to confirm a proposed action, thus resolving what triggered the dialog. The dialog does not set up any events for this button so they need to be set up by the caller.

modifier: Modifier = Modifier

the Modifier to be applied to this dialog

dismissButton: (@Composable () -> Unit)? = null

button which is meant to dismiss the dialog. The dialog does not set up any events for this button so they need to be set up by the caller.

icon: (@Composable () -> Unit)? = null

optional icon that will appear above the title or above the text, in case a title was not provided.

title: (@Composable () -> Unit)? = null

title which should specify the purpose of the dialog. The title is not mandatory, because there may be sufficient information inside the text.

text: (@Composable () -> Unit)? = null

text which presents the details regarding the dialog's purpose.

shape: Shape = AlertDialogDefaults.shape

defines the shape of this dialog's container

containerColor: Color = AlertDialogDefaults.containerColor

the color used for the background of this dialog. Use Color.Transparent to have no color.

iconContentColor: Color = AlertDialogDefaults.iconContentColor

the content color used for the icon.

titleContentColor: Color = AlertDialogDefaults.titleContentColor

the content color used for the title.

textContentColor: Color = AlertDialogDefaults.textContentColor

the content color used for the text.

tonalElevation: Dp = AlertDialogDefaults.TonalElevation

when containerColor is ColorScheme.surface, a translucent primary color overlay is applied on top of the container. A higher tonal elevation value will result in a darker color in light theme and lighter color in dark theme. See also: Surface.

properties: DialogProperties = DialogProperties()

typically platform specific properties to further configure the dialog.

See also
BasicAlertDialog

AssistChip

@Composable
fun AssistChip(
    onClick: () -> Unit,
    label: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    leadingIcon: (@Composable () -> Unit)? = null,
    trailingIcon: (@Composable () -> Unit)? = null,
    shape: Shape = AssistChipDefaults.shape,
    colors: ChipColors = AssistChipDefaults.assistChipColors(),
    elevation: ChipElevation? = AssistChipDefaults.assistChipElevation(),
    border: BorderStroke? = AssistChipDefaults.assistChipBorder(enabled),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design assist chip.

Chips help people enter information, make selections, filter content, or trigger actions. Chips can show multiple interactive elements together in the same area, such as a list of selectable movie times, or a series of email contacts.

Assist chips represent smart or automated actions that can span multiple apps, such as opening a calendar event from the home screen. Assist chips function as though the user asked an assistant to complete the action. They should appear dynamically and contextually in a UI.

Assist chip image

This assist chip is applied with a flat style. If you want an elevated style, use the ElevatedAssistChip.

Example of a flat AssistChip:

import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.AssistChip
import androidx.compose.material3.AssistChipDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier

AssistChip(
    onClick = { /* Do something! */ },
    label = { Text("Assist Chip") },
    leadingIcon = {
        Icon(
            Icons.Filled.Settings,
            contentDescription = "Localized description",
            Modifier.size(AssistChipDefaults.IconSize)
        )
    }
)
Parameters
onClick: () -> Unit

called when this chip is clicked

label: @Composable () -> Unit

text label for this chip

modifier: Modifier = Modifier

the Modifier to be applied to this chip

enabled: Boolean = true

controls the enabled state of this chip. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

leadingIcon: (@Composable () -> Unit)? = null

optional icon at the start of the chip, preceding the label text

trailingIcon: (@Composable () -> Unit)? = null

optional icon at the end of the chip

shape: Shape = AssistChipDefaults.shape

defines the shape of this chip's container, border (when border is not null), and shadow (when using elevation)

colors: ChipColors = AssistChipDefaults.assistChipColors()

ChipColors that will be used to resolve the colors used for this chip in different states. See AssistChipDefaults.assistChipColors.

elevation: ChipElevation? = AssistChipDefaults.assistChipElevation()

ChipElevation used to resolve the elevation for this chip in different states. This controls the size of the shadow below the chip. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See AssistChipDefaults.assistChipElevation.

border: BorderStroke? = AssistChipDefaults.assistChipBorder(enabled)

the border to draw around the container of this chip. Pass null for no border. See AssistChipDefaults.assistChipBorder.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this chip. You can use this to change the chip's appearance or preview the chip in different states. Note that if null is provided, interactions will still happen internally.

@Composable
fun Badge(
    modifier: Modifier = Modifier,
    containerColor: Color = BadgeDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    content: (@Composable RowScope.() -> Unit)? = null
): Unit

A badge represents dynamic information such as a number of pending requests in a navigation bar.

Badges can be icon only or contain short text.

Badge image

See BadgedBox for a top level layout that will properly place the badge relative to content such as text or an icon.

Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this badge

containerColor: Color = BadgeDefaults.containerColor

the color used for the background of this badge

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this badge. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

content: (@Composable RowScope.() -> Unit)? = null

optional content to be rendered inside this badge

BadgedBox

@Composable
fun BadgedBox(
    badge: @Composable BoxScope.() -> Unit,
    modifier: Modifier = Modifier,
    content: @Composable BoxScope.() -> Unit
): Unit

Material Design badge box.

A badge represents dynamic information such as a number of pending requests in a navigation bar.

Badges can be icon only or contain short text.

Badge image

A common use case is to display a badge with navigation bar items. For more information, see Navigation Bar

A simple icon with badge example looks like:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Star
import androidx.compose.material3.Badge
import androidx.compose.material3.BadgedBox
import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics

NavigationBar {
    NavigationBarItem(
        icon = {
            BadgedBox(
                badge = {
                    Badge {
                        val badgeNumber = "8"
                        Text(
                            badgeNumber,
                            modifier =
                                Modifier.semantics {
                                    contentDescription = "$badgeNumber new notifications"
                                }
                        )
                    }
                }
            ) {
                Icon(Icons.Filled.Star, contentDescription = "Favorite")
            }
        },
        selected = false,
        onClick = {}
    )
}
Parameters
badge: @Composable BoxScope.() -> Unit

the badge to be displayed - typically a Badge

modifier: Modifier = Modifier

the Modifier to be applied to this BadgedBox

content: @Composable BoxScope.() -> Unit

the anchor to which this badge will be positioned

BasicAlertDialog

@ExperimentalMaterial3Api
@Composable
fun BasicAlertDialog(
    onDismissRequest: () -> Unit,
    modifier: Modifier = Modifier,
    properties: DialogProperties = DialogProperties(),
    content: @Composable () -> Unit
): Unit

Basic alert dialog dialog.

Dialogs provide important prompts in a user flow. They can require an action, communicate information, or help users accomplish a task.

Basic dialog image

This basic alert dialog expects an arbitrary content that is defined by the caller. Note that your content will need to define its own styling.

By default, the displayed dialog has the minimum height and width that the Material Design spec defines. If required, these constraints can be overwritten by providing a width or height Modifiers.

Basic alert dialog usage with custom content:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.AlertDialogDefaults
import androidx.compose.material3.BasicAlertDialog
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val openDialog = remember { mutableStateOf(true) }

if (openDialog.value) {
    BasicAlertDialog(
        onDismissRequest = {
            // Dismiss the dialog when the user clicks outside the dialog or on the back
            // button. If you want to disable that functionality, simply use an empty
            // onDismissRequest.
            openDialog.value = false
        }
    ) {
        Surface(
            modifier = Modifier.wrapContentWidth().wrapContentHeight(),
            shape = MaterialTheme.shapes.large,
            tonalElevation = AlertDialogDefaults.TonalElevation
        ) {
            Column(modifier = Modifier.padding(16.dp)) {
                Text(
                    text =
                        "This area typically contains the supportive text " +
                            "which presents the details regarding the Dialog's purpose.",
                )
                Spacer(modifier = Modifier.height(24.dp))
                TextButton(
                    onClick = { openDialog.value = false },
                    modifier = Modifier.align(Alignment.End)
                ) {
                    Text("Confirm")
                }
            }
        }
    }
}
Parameters
onDismissRequest: () -> Unit

called when the user tries to dismiss the Dialog by clicking outside or pressing the back button. This is not called when the dismiss button is clicked.

modifier: Modifier = Modifier

the Modifier to be applied to this dialog's content.

properties: DialogProperties = DialogProperties()

typically platform specific properties to further configure the dialog.

content: @Composable () -> Unit

the content of the dialog

@Composable
fun BottomAppBar(
    modifier: Modifier = Modifier,
    containerColor: Color = BottomAppBarDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    tonalElevation: Dp = BottomAppBarDefaults.ContainerElevation,
    contentPadding: PaddingValues = BottomAppBarDefaults.ContentPadding,
    windowInsets: WindowInsets = BottomAppBarDefaults.windowInsets,
    content: @Composable RowScope.() -> Unit
): Unit

Material Design bottom app bar.

A bottom app bar displays navigation and key actions at the bottom of mobile screens.

Bottom app bar image

If you are interested in displaying a FloatingActionButton, consider using another overload.

Also see NavigationBar.

Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this BottomAppBar

containerColor: Color = BottomAppBarDefaults.containerColor

the color used for the background of this BottomAppBar. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this BottomAppBar. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

tonalElevation: Dp = BottomAppBarDefaults.ContainerElevation

when containerColor is ColorScheme.surface, a translucent primary color overlay is applied on top of the container. A higher tonal elevation value will result in a darker color in light theme and lighter color in dark theme. See also: Surface.

contentPadding: PaddingValues = BottomAppBarDefaults.ContentPadding

the padding applied to the content of this BottomAppBar

windowInsets: WindowInsets = BottomAppBarDefaults.windowInsets

a window insets that app bar will respect.

content: @Composable RowScope.() -> Unit

the content of this BottomAppBar. The default layout here is a Row, so content inside will be placed horizontally.

@Composable
fun BottomAppBar(
    actions: @Composable RowScope.() -> Unit,
    modifier: Modifier = Modifier,
    floatingActionButton: (@Composable () -> Unit)? = null,
    containerColor: Color = BottomAppBarDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    tonalElevation: Dp = BottomAppBarDefaults.ContainerElevation,
    contentPadding: PaddingValues = BottomAppBarDefaults.ContentPadding,
    windowInsets: WindowInsets = BottomAppBarDefaults.windowInsets
): Unit

Material Design bottom app bar.

A bottom app bar displays navigation and key actions at the bottom of mobile screens.

Bottom app bar image

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton

BottomAppBar(
    actions = {
        IconButton(onClick = { /* doSomething() */ }) {
            Icon(Icons.Filled.Menu, contentDescription = "Localized description")
        }
    }
)

It can optionally display a FloatingActionButton embedded at the end of the BottomAppBar.

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.BottomAppBarDefaults
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton

BottomAppBar(
    actions = {
        IconButton(onClick = { /* doSomething() */ }) {
            Icon(Icons.Filled.Check, contentDescription = "Localized description")
        }
        IconButton(onClick = { /* doSomething() */ }) {
            Icon(
                Icons.Filled.Edit,
                contentDescription = "Localized description",
            )
        }
    },
    floatingActionButton = {
        FloatingActionButton(
            onClick = { /* do something */ },
            containerColor = BottomAppBarDefaults.bottomAppBarFabColor,
            elevation = FloatingActionButtonDefaults.bottomAppBarFabElevation()
        ) {
            Icon(Icons.Filled.Add, "Localized description")
        }
    }
)

Also see NavigationBar.

Parameters
actions: @Composable RowScope.() -> Unit

the icon content of this BottomAppBar. The default layout here is a Row, so content inside will be placed horizontally.

modifier: Modifier = Modifier

the Modifier to be applied to this BottomAppBar

floatingActionButton: (@Composable () -> Unit)? = null

optional floating action button at the end of this BottomAppBar

containerColor: Color = BottomAppBarDefaults.containerColor

the color used for the background of this BottomAppBar. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this BottomAppBar. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

tonalElevation: Dp = BottomAppBarDefaults.ContainerElevation

when containerColor is ColorScheme.surface, a translucent primary color overlay is applied on top of the container. A higher tonal elevation value will result in a darker color in light theme and lighter color in dark theme. See also: Surface.

contentPadding: PaddingValues = BottomAppBarDefaults.ContentPadding

the padding applied to the content of this BottomAppBar

windowInsets: WindowInsets = BottomAppBarDefaults.windowInsets

a window insets that app bar will respect.

@ExperimentalMaterial3ExpressiveApi
@Composable
fun BottomAppBar(
    horizontalArrangement: Arrangement.Horizontal,
    modifier: Modifier = Modifier,
    containerColor: Color = BottomAppBarDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    contentPadding: PaddingValues = PaddingValues(horizontal = 16.dp),
    windowInsets: WindowInsets = BottomAppBarDefaults.windowInsets,
    scrollBehavior: BottomAppBarScrollBehavior? = null,
    content: @Composable RowScope.() -> Unit
): Unit

Material Design bottom app bar.

A bottom app bar displays navigation and key actions at the bottom of mobile screens.

Bottom app bar image

If you are interested in displaying a FloatingActionButton, consider using another overload that takes a FloatingActionButton parameter.

Also see NavigationBar.

A bottom app bar that specifies an horizontalArrangement and uses a scrollBehavior to customize its nested scrolling behavior when working in conjunction with a scrolling content looks like:

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.ArrowForward
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.BottomAppBarDefaults
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp

val context = LocalContext.current
val isTouchExplorationEnabled = remember {
    val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
    am.isEnabled && am.isTouchExplorationEnabled
}
val scrollBehavior = BottomAppBarDefaults.exitAlwaysScrollBehavior()
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    bottomBar = {
        BottomAppBar(
            horizontalArrangement = Arrangement.SpaceAround,
            contentPadding = PaddingValues(horizontal = 0.dp),
            scrollBehavior = if (!isTouchExplorationEnabled) scrollBehavior else null,
            content = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        Icons.AutoMirrored.Filled.ArrowBack,
                        contentDescription = "Localized description"
                    )
                }
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        Icons.AutoMirrored.Filled.ArrowForward,
                        contentDescription = "Localized description"
                    )
                }
                FilledIconButton(
                    modifier = Modifier.width(56.dp),
                    onClick = { /* doSomething() */ }
                ) {
                    Icon(Icons.Filled.Add, contentDescription = "Localized description")
                }
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(Icons.Filled.Check, contentDescription = "Localized description")
                }
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(Icons.Filled.Edit, contentDescription = "Localized description")
                }
            }
        )
    },
    content = { innerPadding ->
        LazyColumn(
            contentPadding = innerPadding,
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            val list = (0..75).map { it.toString() }
            items(count = list.size) {
                Text(
                    text = list[it],
                    style = MaterialTheme.typography.bodyLarge,
                    modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                )
            }
        }
    }
)
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.ArrowForward
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.BottomAppBarDefaults
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp

val context = LocalContext.current
val isTouchExplorationEnabled = remember {
    val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
    am.isEnabled && am.isTouchExplorationEnabled
}
val scrollBehavior = BottomAppBarDefaults.exitAlwaysScrollBehavior()
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    bottomBar = {
        BottomAppBar(
            horizontalArrangement = Arrangement.SpaceBetween,
            scrollBehavior = if (!isTouchExplorationEnabled) scrollBehavior else null,
            content = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        Icons.AutoMirrored.Filled.ArrowBack,
                        contentDescription = "Localized description"
                    )
                }
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        Icons.AutoMirrored.Filled.ArrowForward,
                        contentDescription = "Localized description"
                    )
                }
                FilledIconButton(
                    modifier = Modifier.width(56.dp),
                    onClick = { /* doSomething() */ }
                ) {
                    Icon(Icons.Filled.Add, contentDescription = "Localized description")
                }
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(Icons.Filled.Check, contentDescription = "Localized description")
                }
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(Icons.Filled.Edit, contentDescription = "Localized description")
                }
            }
        )
    },
    content = { innerPadding ->
        LazyColumn(
            contentPadding = innerPadding,
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            val list = (0..75).map { it.toString() }
            items(count = list.size) {
                Text(
                    text = list[it],
                    style = MaterialTheme.typography.bodyLarge,
                    modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                )
            }
        }
    }
)
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.ArrowForward
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.BottomAppBarDefaults
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp

val context = LocalContext.current
val isTouchExplorationEnabled = remember {
    val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
    am.isEnabled && am.isTouchExplorationEnabled
}
val scrollBehavior = BottomAppBarDefaults.exitAlwaysScrollBehavior()
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    bottomBar = {
        BottomAppBar(
            horizontalArrangement = Arrangement.SpaceEvenly,
            contentPadding = PaddingValues(horizontal = 0.dp),
            scrollBehavior = if (!isTouchExplorationEnabled) scrollBehavior else null,
            content = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        Icons.AutoMirrored.Filled.ArrowBack,
                        contentDescription = "Localized description"
                    )
                }
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        Icons.AutoMirrored.Filled.ArrowForward,
                        contentDescription = "Localized description"
                    )
                }
                FilledIconButton(
                    modifier = Modifier.width(56.dp),
                    onClick = { /* doSomething() */ }
                ) {
                    Icon(Icons.Filled.Add, contentDescription = "Localized description")
                }
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(Icons.Filled.Check, contentDescription = "Localized description")
                }
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(Icons.Filled.Edit, contentDescription = "Localized description")
                }
            }
        )
    },
    content = { innerPadding ->
        LazyColumn(
            contentPadding = innerPadding,
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            val list = (0..75).map { it.toString() }
            items(count = list.size) {
                Text(
                    text = list[it],
                    style = MaterialTheme.typography.bodyLarge,
                    modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                )
            }
        }
    }
)
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.ArrowForward
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.BottomAppBarDefaults
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp

val context = LocalContext.current
val isTouchExplorationEnabled = remember {
    val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
    am.isEnabled && am.isTouchExplorationEnabled
}
val scrollBehavior = BottomAppBarDefaults.exitAlwaysScrollBehavior()
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    bottomBar = {
        BottomAppBar(
            horizontalArrangement = BottomAppBarDefaults.HorizontalArrangement,
            scrollBehavior = if (!isTouchExplorationEnabled) scrollBehavior else null,
            content = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        Icons.AutoMirrored.Filled.ArrowBack,
                        contentDescription = "Localized description"
                    )
                }
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        Icons.AutoMirrored.Filled.ArrowForward,
                        contentDescription = "Localized description"
                    )
                }
                FilledIconButton(
                    modifier = Modifier.width(56.dp),
                    onClick = { /* doSomething() */ }
                ) {
                    Icon(Icons.Filled.Add, contentDescription = "Localized description")
                }
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(Icons.Filled.Check, contentDescription = "Localized description")
                }
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(Icons.Filled.Edit, contentDescription = "Localized description")
                }
            }
        )
    },
    content = { innerPadding ->
        LazyColumn(
            contentPadding = innerPadding,
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            val list = (0..75).map { it.toString() }
            items(count = list.size) {
                Text(
                    text = list[it],
                    style = MaterialTheme.typography.bodyLarge,
                    modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                )
            }
        }
    }
)
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.ArrowForward
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.BottomAppBarDefaults
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp

val context = LocalContext.current
val isTouchExplorationEnabled = remember {
    val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
    am.isEnabled && am.isTouchExplorationEnabled
}
val scrollBehavior = BottomAppBarDefaults.exitAlwaysScrollBehavior()
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    bottomBar = {
        BottomAppBar(
            horizontalArrangement = BottomAppBarDefaults.HorizontalArrangement,
            scrollBehavior = if (!isTouchExplorationEnabled) scrollBehavior else null,
            containerColor =
                MaterialTheme.colorScheme.primaryContainer, // TODO(b/356885344): tokens
            content = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        Icons.AutoMirrored.Filled.ArrowBack,
                        contentDescription = "Localized description"
                    )
                }
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        Icons.AutoMirrored.Filled.ArrowForward,
                        contentDescription = "Localized description"
                    )
                }
                FilledIconButton(
                    modifier = Modifier.width(56.dp),
                    onClick = { /* doSomething() */ }
                ) {
                    Icon(Icons.Filled.Add, contentDescription = "Localized description")
                }
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(Icons.Filled.Check, contentDescription = "Localized description")
                }
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(Icons.Filled.Edit, contentDescription = "Localized description")
                }
            }
        )
    },
    content = { innerPadding ->
        LazyColumn(
            contentPadding = innerPadding,
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            val list = (0..75).map { it.toString() }
            items(count = list.size) {
                Text(
                    text = list[it],
                    style = MaterialTheme.typography.bodyLarge,
                    modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                )
            }
        }
    }
)
Parameters
horizontalArrangement: Arrangement.Horizontal

the horizontal arrangement of the content.

modifier: Modifier = Modifier

the Modifier to be applied to this BottomAppBar

containerColor: Color = BottomAppBarDefaults.containerColor

the color used for the background of this BottomAppBar. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this BottomAppBar. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

contentPadding: PaddingValues = PaddingValues(horizontal = 16.dp)

the padding applied to the content of this BottomAppBar

windowInsets: WindowInsets = BottomAppBarDefaults.windowInsets

a window insets that app bar will respect.

scrollBehavior: BottomAppBarScrollBehavior? = null

a BottomAppBarScrollBehavior which holds various offset values that will be applied by this bottom app bar to set up its height. A scroll behavior is designed to work in conjunction with a scrolled content to change the bottom app bar appearance as the content scrolls. See BottomAppBarScrollBehavior.nestedScrollConnection.

content: @Composable RowScope.() -> Unit

the content of this BottomAppBar. The default layout here is a Row, so content inside will be placed horizontally.

@ExperimentalMaterial3Api
@Composable
fun BottomAppBar(
    modifier: Modifier = Modifier,
    containerColor: Color = BottomAppBarDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    tonalElevation: Dp = BottomAppBarDefaults.ContainerElevation,
    contentPadding: PaddingValues = BottomAppBarDefaults.ContentPadding,
    windowInsets: WindowInsets = BottomAppBarDefaults.windowInsets,
    scrollBehavior: BottomAppBarScrollBehavior? = null,
    content: @Composable RowScope.() -> Unit
): Unit

Material Design bottom app bar.

A bottom app bar displays navigation and key actions at the bottom of mobile screens.

Bottom app bar image

If you are interested in displaying a FloatingActionButton, consider using another overload.

Also see NavigationBar.

Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this BottomAppBar

containerColor: Color = BottomAppBarDefaults.containerColor

the color used for the background of this BottomAppBar. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this BottomAppBar. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

tonalElevation: Dp = BottomAppBarDefaults.ContainerElevation

when containerColor is ColorScheme.surface, a translucent primary color overlay is applied on top of the container. A higher tonal elevation value will result in a darker color in light theme and lighter color in dark theme. See also: Surface.

contentPadding: PaddingValues = BottomAppBarDefaults.ContentPadding

the padding applied to the content of this BottomAppBar

windowInsets: WindowInsets = BottomAppBarDefaults.windowInsets

a window insets that app bar will respect.

scrollBehavior: BottomAppBarScrollBehavior? = null

a BottomAppBarScrollBehavior which holds various offset values that will be applied by this bottom app bar to set up its height. A scroll behavior is designed to work in conjunction with a scrolled content to change the bottom app bar appearance as the content scrolls. See BottomAppBarScrollBehavior.nestedScrollConnection.

content: @Composable RowScope.() -> Unit

the content of this BottomAppBar. The default layout here is a Row, so content inside will be placed horizontally.

@ExperimentalMaterial3Api
@Composable
fun BottomAppBar(
    actions: @Composable RowScope.() -> Unit,
    modifier: Modifier = Modifier,
    floatingActionButton: (@Composable () -> Unit)? = null,
    containerColor: Color = BottomAppBarDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    tonalElevation: Dp = BottomAppBarDefaults.ContainerElevation,
    contentPadding: PaddingValues = BottomAppBarDefaults.ContentPadding,
    windowInsets: WindowInsets = BottomAppBarDefaults.windowInsets,
    scrollBehavior: BottomAppBarScrollBehavior? = null
): Unit

Material Design bottom app bar.

A bottom app bar displays navigation and key actions at the bottom of mobile screens.

Bottom app bar image

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton

BottomAppBar(
    actions = {
        IconButton(onClick = { /* doSomething() */ }) {
            Icon(Icons.Filled.Menu, contentDescription = "Localized description")
        }
    }
)

It can optionally display a FloatingActionButton embedded at the end of the BottomAppBar.

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.BottomAppBarDefaults
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton

BottomAppBar(
    actions = {
        IconButton(onClick = { /* doSomething() */ }) {
            Icon(Icons.Filled.Check, contentDescription = "Localized description")
        }
        IconButton(onClick = { /* doSomething() */ }) {
            Icon(
                Icons.Filled.Edit,
                contentDescription = "Localized description",
            )
        }
    },
    floatingActionButton = {
        FloatingActionButton(
            onClick = { /* do something */ },
            containerColor = BottomAppBarDefaults.bottomAppBarFabColor,
            elevation = FloatingActionButtonDefaults.bottomAppBarFabElevation()
        ) {
            Icon(Icons.Filled.Add, "Localized description")
        }
    }
)

A bottom app bar that uses a scrollBehavior to customize its nested scrolling behavior when working in conjunction with a scrolling content looks like:

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.BottomAppBarDefaults
import androidx.compose.material3.FabPosition
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp

val context = LocalContext.current
val isTouchExplorationEnabled = remember {
    val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
    am.isEnabled && am.isTouchExplorationEnabled
}
val scrollBehavior = BottomAppBarDefaults.exitAlwaysScrollBehavior()
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    bottomBar = {
        BottomAppBar(
            actions = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(Icons.Filled.Check, contentDescription = "Localized description")
                }
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(Icons.Filled.Edit, contentDescription = "Localized description")
                }
            },
            scrollBehavior = if (!isTouchExplorationEnabled) scrollBehavior else null,
        )
    },
    floatingActionButton = {
        FloatingActionButton(
            modifier = Modifier.offset(y = 4.dp),
            onClick = { /* do something */ },
            containerColor = BottomAppBarDefaults.bottomAppBarFabColor,
            elevation = FloatingActionButtonDefaults.bottomAppBarFabElevation()
        ) {
            Icon(Icons.Filled.Add, "Localized description")
        }
    },
    floatingActionButtonPosition = FabPosition.EndOverlay,
    content = { innerPadding ->
        LazyColumn(
            contentPadding = innerPadding,
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            val list = (0..75).map { it.toString() }
            items(count = list.size) {
                Text(
                    text = list[it],
                    style = MaterialTheme.typography.bodyLarge,
                    modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                )
            }
        }
    }
)

Also see NavigationBar.

Parameters
actions: @Composable RowScope.() -> Unit

the icon content of this BottomAppBar. The default layout here is a Row, so content inside will be placed horizontally.

modifier: Modifier = Modifier

the Modifier to be applied to this BottomAppBar

floatingActionButton: (@Composable () -> Unit)? = null

optional floating action button at the end of this BottomAppBar

containerColor: Color = BottomAppBarDefaults.containerColor

the color used for the background of this BottomAppBar. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this BottomAppBar. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

tonalElevation: Dp = BottomAppBarDefaults.ContainerElevation

when containerColor is ColorScheme.surface, a translucent primary color overlay is applied on top of the container. A higher tonal elevation value will result in a darker color in light theme and lighter color in dark theme. See also: Surface.

contentPadding: PaddingValues = BottomAppBarDefaults.ContentPadding

the padding applied to the content of this BottomAppBar

windowInsets: WindowInsets = BottomAppBarDefaults.windowInsets

a window insets that app bar will respect.

scrollBehavior: BottomAppBarScrollBehavior? = null

a BottomAppBarScrollBehavior which holds various offset values that will be applied by this bottom app bar to set up its height. A scroll behavior is designed to work in conjunction with a scrolled content to change the bottom app bar appearance as the content scrolls. See BottomAppBarScrollBehavior.nestedScrollConnection.

BottomAppBarState

@ExperimentalMaterial3Api
fun BottomAppBarState(
    initialHeightOffsetLimit: Float,
    initialHeightOffset: Float,
    initialContentOffset: Float
): BottomAppBarState

Creates a BottomAppBarState.

Parameters
initialHeightOffsetLimit: Float

the initial value for BottomAppBarState.heightOffsetLimit, which represents the pixel limit that a bottom app bar is allowed to collapse when the scrollable content is scrolled

initialHeightOffset: Float

the initial value for BottomAppBarState.heightOffset. The initial offset height offset should be between zero and initialHeightOffsetLimit.

initialContentOffset: Float

the initial value for BottomAppBarState.contentOffset

BottomSheetScaffold

@Composable
@ExperimentalMaterial3Api
fun BottomSheetScaffold(
    sheetContent: @Composable ColumnScope.() -> Unit,
    modifier: Modifier = Modifier,
    scaffoldState: BottomSheetScaffoldState = rememberBottomSheetScaffoldState(),
    sheetPeekHeight: Dp = BottomSheetDefaults.SheetPeekHeight,
    sheetMaxWidth: Dp = BottomSheetDefaults.SheetMaxWidth,
    sheetShape: Shape = BottomSheetDefaults.ExpandedShape,
    sheetContainerColor: Color = BottomSheetDefaults.ContainerColor,
    sheetContentColor: Color = contentColorFor(sheetContainerColor),
    sheetTonalElevation: Dp = 0.dp,
    sheetShadowElevation: Dp = BottomSheetDefaults.Elevation,
    sheetDragHandle: (@Composable () -> Unit)? = { BottomSheetDefaults.DragHandle() },
    sheetSwipeEnabled: Boolean = true,
    topBar: (@Composable () -> Unit)? = null,
    snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) },
    containerColor: Color = MaterialTheme.colorScheme.surface,
    contentColor: Color = contentColorFor(containerColor),
    content: @Composable (PaddingValues) -> Unit
): Unit

Material Design standard bottom sheet scaffold.

Standard bottom sheets co-exist with the screen’s main UI region and allow for simultaneously viewing and interacting with both regions. They are commonly used to keep a feature or secondary content visible on screen when content in main UI region is frequently scrolled or panned.

Bottom sheet image

This component provides API to put together several material components to construct your screen, by ensuring proper layout strategy for them and collecting necessary data so these components will work together correctly.

A simple example of a standard bottom sheet looks like this:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.BottomSheetScaffold
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.material3.rememberBottomSheetScaffoldState
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val scope = rememberCoroutineScope()
val scaffoldState = rememberBottomSheetScaffoldState()

BottomSheetScaffold(
    scaffoldState = scaffoldState,
    sheetPeekHeight = 128.dp,
    sheetContent = {
        Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
            Box(Modifier.fillMaxWidth().height(128.dp), contentAlignment = Alignment.Center) {
                Text("Swipe up to expand sheet")
            }
            Text("Sheet content")
            Button(
                modifier = Modifier.padding(bottom = 64.dp),
                onClick = { scope.launch { scaffoldState.bottomSheetState.partialExpand() } }
            ) {
                Text("Click to collapse sheet")
            }
        }
    }
) { innerPadding ->
    Box(
        modifier = Modifier.fillMaxSize().padding(innerPadding),
        contentAlignment = Alignment.Center
    ) {
        Text("Scaffold Content")
    }
}
Parameters
sheetContent: @Composable ColumnScope.() -> Unit

the content of the bottom sheet

modifier: Modifier = Modifier

the Modifier to be applied to the root of the scaffold

scaffoldState: BottomSheetScaffoldState = rememberBottomSheetScaffoldState()

the state of the bottom sheet scaffold

sheetPeekHeight: Dp = BottomSheetDefaults.SheetPeekHeight

the height of the bottom sheet when it is collapsed

sheetMaxWidth: Dp = BottomSheetDefaults.SheetMaxWidth

Dp that defines what the maximum width the sheet will take. Pass in Dp.Unspecified for a sheet that spans the entire screen width.

sheetShape: Shape = BottomSheetDefaults.ExpandedShape

the shape of the bottom sheet

sheetContainerColor: Color = BottomSheetDefaults.ContainerColor

the background color of the bottom sheet

sheetContentColor: Color = contentColorFor(sheetContainerColor)

the preferred content color provided by the bottom sheet to its children. Defaults to the matching content color for sheetContainerColor, or if that is not a color from the theme, this will keep the same content color set above the bottom sheet.

sheetTonalElevation: Dp = 0.dp

when sheetContainerColor is ColorScheme.surface, a translucent primary color overlay is applied on top of the container. A higher tonal elevation value will result in a darker color in light theme and lighter color in dark theme. See also: Surface.

sheetShadowElevation: Dp = BottomSheetDefaults.Elevation

the shadow elevation of the bottom sheet

sheetDragHandle: (@Composable () -> Unit)? = { BottomSheetDefaults.DragHandle() }

optional visual marker to pull the scaffold's bottom sheet

sheetSwipeEnabled: Boolean = true

whether the sheet swiping is enabled and should react to the user's input

topBar: (@Composable () -> Unit)? = null

top app bar of the screen, typically a TopAppBar

snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) }

component to host Snackbars that are pushed to be shown via SnackbarHostState.showSnackbar, typically a SnackbarHost

containerColor: Color = MaterialTheme.colorScheme.surface

the color used for the background of this scaffold. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this scaffold. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

content: @Composable (PaddingValues) -> Unit

content of the screen. The lambda receives a PaddingValues that should be applied to the content root via Modifier.padding and Modifier.consumeWindowInsets to properly offset top and bottom bars. If using Modifier.verticalScroll, apply this modifier to the child of the scroll, and not on the scroll itself.

@Composable
fun Button(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shape: Shape = ButtonDefaults.shape,
    colors: ButtonColors = ButtonDefaults.buttonColors(),
    elevation: ButtonElevation? = ButtonDefaults.buttonElevation(),
    border: BorderStroke? = null,
    contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
    interactionSource: MutableInteractionSource? = null,
    content: @Composable RowScope.() -> Unit
): Unit

Material Design button.

Buttons help people initiate actions, from sending an email, to sharing a document, to liking a post.

Filled button image

Filled buttons are high-emphasis buttons. Filled buttons have the most visual impact after the FloatingActionButton, and should be used for important, final actions that complete a flow, like "Save", "Join now", or "Confirm".

import androidx.compose.material3.Button
import androidx.compose.material3.Text

Button(onClick = { /* Do something! */ }) { Text("Button") }
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier

Button(
    onClick = { /* Do something! */ },
    contentPadding = ButtonDefaults.ButtonWithIconContentPadding
) {
    Icon(
        Icons.Filled.Favorite,
        contentDescription = "Localized description",
        modifier = Modifier.size(ButtonDefaults.IconSize)
    )
    Spacer(Modifier.size(ButtonDefaults.IconSpacing))
    Text("Like")
}

Button that uses a square shape instead of the default round shape:

import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Text

Button(onClick = { /* Do something! */ }, shape = ButtonDefaults.squareShape) { Text("Button") }

Button that utilizes the small design content padding:

import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Text

Button(
    onClick = { /* Do something! */ },
    contentPadding = ButtonDefaults.SmallButtonContentPadding
) {
    Text("Button")
}

Button uses the small design spec as default. For a Button that uses the design for extra small, medium, large, or extra large buttons:

import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier

Button(
    onClick = { /* Do something! */ },
    modifier = Modifier.heightIn(ButtonDefaults.XSmallContainerHeight),
    contentPadding = ButtonDefaults.XSmallContentPadding
) {
    Icon(
        Icons.Filled.Edit,
        contentDescription = "Localized description",
        modifier = Modifier.size(ButtonDefaults.XSmallIconSize)
    )
    Spacer(Modifier.size(ButtonDefaults.XSmallIconSpacing))
    Text("Label")
}
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier

Button(
    onClick = { /* Do something! */ },
    modifier = Modifier.heightIn(ButtonDefaults.MediumContainerHeight),
    contentPadding = ButtonDefaults.MediumContentPadding
) {
    Icon(
        Icons.Filled.Edit,
        contentDescription = "Localized description",
        modifier = Modifier.size(ButtonDefaults.MediumIconSize)
    )
    Spacer(Modifier.size(ButtonDefaults.MediumIconSpacing))
    Text(text = "Label", style = MaterialTheme.typography.titleMedium)
}
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier

Button(
    onClick = { /* Do something! */ },
    modifier = Modifier.heightIn(ButtonDefaults.LargeContainerHeight),
    contentPadding = ButtonDefaults.LargeContentPadding
) {
    Icon(
        Icons.Filled.Edit,
        contentDescription = "Localized description",
        modifier = Modifier.size(ButtonDefaults.LargeIconSize)
    )
    Spacer(Modifier.size(ButtonDefaults.LargeIconSpacing))
    Text(text = "Label", style = MaterialTheme.typography.headlineSmall)
}
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier

Button(
    onClick = { /* Do something! */ },
    modifier = Modifier.heightIn(ButtonDefaults.XLargeContainerHeight),
    contentPadding = ButtonDefaults.XLargeContentPadding
) {
    Icon(
        Icons.Filled.Edit,
        contentDescription = "Localized description",
        modifier = Modifier.size(ButtonDefaults.XLargeIconSize)
    )
    Spacer(Modifier.size(ButtonDefaults.XLargeIconSpacing))
    Text(text = "Label", style = MaterialTheme.typography.headlineLarge)
}

Choose the best button for an action based on the amount of emphasis it needs. The more important an action is, the higher emphasis its button should be.

The default text style for internal Text components will be set to Typography.labelLarge.

Parameters
onClick: () -> Unit

called when this button is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this button

enabled: Boolean = true

controls the enabled state of this button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

shape: Shape = ButtonDefaults.shape

defines the shape of this button's container, border (when border is not null), and shadow (when using elevation)

colors: ButtonColors = ButtonDefaults.buttonColors()

ButtonColors that will be used to resolve the colors for this button in different states. See ButtonDefaults.buttonColors.

elevation: ButtonElevation? = ButtonDefaults.buttonElevation()

ButtonElevation used to resolve the elevation for this button in different states. This controls the size of the shadow below the button. See ButtonElevation.shadowElevation.

border: BorderStroke? = null

the border to draw around the container of this button

contentPadding: PaddingValues = ButtonDefaults.ContentPadding

the spacing values to apply internally between the container and the content

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this button. You can use this to change the button's appearance or preview the button in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable RowScope.() -> Unit

The content displayed on the button, expected to be text, icon or image.

@Composable
@ExperimentalMaterial3ExpressiveApi
fun ButtonGroup(
    modifier: Modifier = Modifier,
    animateFraction: @FloatRange(from = 0.0) Float = ButtonGroupDefaults.animateFraction,
    horizontalArrangement: Arrangement.Horizontal = Arrangement.spacedBy(ButtonGroupDefaults.spaceBetween),
    content: @Composable ButtonGroupScope.() -> Unit
): Unit

TODO link to mio page when available.

A layout composable that places its children in a horizontal sequence. When a child uses Modifier.interactionSourceData with a relevant MutableInteractionSource, this button group can listen to the interactions and expand the width of the pressed child element as well as compress the neighboring child elements. Material3 components already use Modifier.interactionSourceData and will behave as expected.

TODO link to an image when available

import androidx.compose.foundation.layout.width
import androidx.compose.material3.ButtonGroup
import androidx.compose.material3.Text
import androidx.compose.material3.ToggleButton
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastForEachIndexed

ButtonGroup {
    val options = listOf("A", "B", "C", "D")
    val checked = remember { mutableStateListOf(false, false, false, false) }
    val modifiers =
        listOf(
            Modifier.weight(1.5f),
            Modifier.weight(1f),
            Modifier.width(90.dp),
            Modifier.weight(1f)
        )
    options.fastForEachIndexed { index, label ->
        ToggleButton(
            checked = checked[index],
            onCheckedChange = { checked[index] = it },
            modifier = modifiers[index]
        ) {
            Text(label)
        }
    }
}

A connected button group is a variant of a button group that have leading and trailing buttons that are asymmetric in shape and are used to make a selection.

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Coffee
import androidx.compose.material.icons.filled.Restaurant
import androidx.compose.material.icons.filled.Work
import androidx.compose.material.icons.outlined.Coffee
import androidx.compose.material.icons.outlined.Restaurant
import androidx.compose.material.icons.outlined.Work
import androidx.compose.material3.ButtonGroup
import androidx.compose.material3.ButtonGroupDefaults
import androidx.compose.material3.ButtonShapes
import androidx.compose.material3.Icon
import androidx.compose.material3.ShapeDefaults
import androidx.compose.material3.Text
import androidx.compose.material3.ToggleButton
import androidx.compose.material3.ToggleButtonDefaults
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val startButtonShapes =
    ButtonShapes(
        shape = ButtonGroupDefaults.connectedLeadingButtonShape,
        pressedShape = ButtonGroupDefaults.connectedLeadingButtonPressShape,
        checkedShape = ToggleButtonDefaults.checkedShape
    )
val middleButtonShapes =
    ButtonShapes(
        shape = ShapeDefaults.Small,
        pressedShape = ToggleButtonDefaults.pressedShape,
        checkedShape = ToggleButtonDefaults.checkedShape
    )
val endButtonShapes =
    ButtonShapes(
        shape = ButtonGroupDefaults.connectedTrailingButtonShape,
        pressedShape = ButtonGroupDefaults.connectedTrailingButtonPressShape,
        checkedShape = ToggleButtonDefaults.checkedShape
    )
val options = listOf("Work", "Restaurant", "Coffee")
val unCheckedIcons =
    listOf(Icons.Outlined.Work, Icons.Outlined.Restaurant, Icons.Outlined.Coffee)
val checkedIcons = listOf(Icons.Filled.Work, Icons.Filled.Restaurant, Icons.Filled.Coffee)
val shapes = listOf(startButtonShapes, middleButtonShapes, endButtonShapes)
val checked = remember { mutableStateListOf(false, false, false) }

ButtonGroup(
    modifier = Modifier.padding(horizontal = 8.dp),
    horizontalArrangement = Arrangement.spacedBy(ButtonGroupDefaults.connectedSpaceBetween),
    animateFraction = 0f
) {
    options.forEachIndexed { index, label ->
        ToggleButton(
            checked = checked[index],
            onCheckedChange = { checked[index] = it },
            shapes = shapes[index]
        ) {
            Icon(
                if (checked[index]) checkedIcons[index] else unCheckedIcons[index],
                contentDescription = "Localized description"
            )
            Spacer(Modifier.size(ToggleButtonDefaults.IconSpacing))
            Text(label)
        }
    }
}
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Coffee
import androidx.compose.material.icons.filled.Restaurant
import androidx.compose.material.icons.filled.Work
import androidx.compose.material.icons.outlined.Coffee
import androidx.compose.material.icons.outlined.Restaurant
import androidx.compose.material.icons.outlined.Work
import androidx.compose.material3.ButtonGroup
import androidx.compose.material3.ButtonGroupDefaults
import androidx.compose.material3.ButtonShapes
import androidx.compose.material3.Icon
import androidx.compose.material3.ShapeDefaults
import androidx.compose.material3.Text
import androidx.compose.material3.ToggleButton
import androidx.compose.material3.ToggleButtonDefaults
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val startButtonShapes =
    ButtonShapes(
        shape = ButtonGroupDefaults.connectedLeadingButtonShape,
        pressedShape = ButtonGroupDefaults.connectedLeadingButtonPressShape,
        checkedShape = ToggleButtonDefaults.checkedShape
    )
val middleButtonShapes =
    ButtonShapes(
        shape = ShapeDefaults.Small,
        pressedShape = ToggleButtonDefaults.pressedShape,
        checkedShape = ToggleButtonDefaults.checkedShape
    )
val endButtonShapes =
    ButtonShapes(
        shape = ButtonGroupDefaults.connectedTrailingButtonShape,
        pressedShape = ButtonGroupDefaults.connectedTrailingButtonPressShape,
        checkedShape = ToggleButtonDefaults.checkedShape
    )
val options = listOf("Work", "Restaurant", "Coffee")
val unCheckedIcons =
    listOf(Icons.Outlined.Work, Icons.Outlined.Restaurant, Icons.Outlined.Coffee)
val checkedIcons = listOf(Icons.Filled.Work, Icons.Filled.Restaurant, Icons.Filled.Coffee)
val shapes = listOf(startButtonShapes, middleButtonShapes, endButtonShapes)
var selectedIndex by remember { mutableIntStateOf(0) }

ButtonGroup(
    modifier = Modifier.padding(horizontal = 8.dp),
    horizontalArrangement = Arrangement.spacedBy(ButtonGroupDefaults.connectedSpaceBetween),
    animateFraction = 0f
) {
    options.forEachIndexed { index, label ->
        ToggleButton(
            checked = selectedIndex == index,
            onCheckedChange = { selectedIndex = index },
            shapes = shapes[index]
        ) {
            Icon(
                if (selectedIndex == index) checkedIcons[index] else unCheckedIcons[index],
                contentDescription = "Localized description"
            )
            Spacer(Modifier.size(ToggleButtonDefaults.IconSpacing))
            Text(label)
        }
    }
}
Parameters
modifier: Modifier = Modifier

the Modifier to be applied to the button group.

animateFraction: @FloatRange(from = 0.0) Float = ButtonGroupDefaults.animateFraction

the percentage, represented by a float, of the width of the interacted child element that will be used to expand the interacted child element as well as compress the neighboring children.

horizontalArrangement: Arrangement.Horizontal = Arrangement.spacedBy(ButtonGroupDefaults.spaceBetween)

The horizontal arrangement of the button group's children.

content: @Composable ButtonGroupScope.() -> Unit

the content displayed in the button group, expected to use a Material3 component or a composable that is tagged with Modifier.interactionSourceData.

@Composable
fun Card(
    modifier: Modifier = Modifier,
    shape: Shape = CardDefaults.shape,
    colors: CardColors = CardDefaults.cardColors(),
    elevation: CardElevation = CardDefaults.cardElevation(),
    border: BorderStroke? = null,
    content: @Composable ColumnScope.() -> Unit
): Unit

Material Design filled card.

Cards contain contain content and actions that relate information about a subject. Filled cards provide subtle separation from the background. This has less emphasis than elevated or outlined cards.

This Card does not handle input events - see the other Card overloads if you want a clickable or selectable Card.

Filled card image

Card sample:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Card
import androidx.compose.material3.Text
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

Card(Modifier.size(width = 180.dp, height = 100.dp)) {
    Box(Modifier.fillMaxSize()) { Text("Card content", Modifier.align(Alignment.Center)) }
}
Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this card

shape: Shape = CardDefaults.shape

defines the shape of this card's container, border (when border is not null), and shadow (when using elevation)

colors: CardColors = CardDefaults.cardColors()

CardColors that will be used to resolve the colors used for this card in different states. See CardDefaults.cardColors.

elevation: CardElevation = CardDefaults.cardElevation()

CardElevation used to resolve the elevation for this card in different states. This controls the size of the shadow below the card. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See also: Surface.

border: BorderStroke? = null

the border to draw around the container of this card

content: @Composable ColumnScope.() -> Unit

The content displayed on the card

@Composable
fun Card(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shape: Shape = CardDefaults.shape,
    colors: CardColors = CardDefaults.cardColors(),
    elevation: CardElevation = CardDefaults.cardElevation(),
    border: BorderStroke? = null,
    interactionSource: MutableInteractionSource? = null,
    content: @Composable ColumnScope.() -> Unit
): Unit

Material Design filled card.

Cards contain contain content and actions that relate information about a subject. Filled cards provide subtle separation from the background. This has less emphasis than elevated or outlined cards.

This Card handles click events, calling its onClick lambda.

Filled card image

Clickable card sample:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Card
import androidx.compose.material3.Text
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

Card(
    onClick = { /* Do something */ },
    modifier = Modifier.size(width = 180.dp, height = 100.dp)
) {
    Box(Modifier.fillMaxSize()) { Text("Clickable", Modifier.align(Alignment.Center)) }
}
Parameters
onClick: () -> Unit

called when this card is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this card

enabled: Boolean = true

controls the enabled state of this card. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

shape: Shape = CardDefaults.shape

defines the shape of this card's container, border (when border is not null), and shadow (when using elevation)

colors: CardColors = CardDefaults.cardColors()

CardColors that will be used to resolve the color(s) used for this card in different states. See CardDefaults.cardColors.

elevation: CardElevation = CardDefaults.cardElevation()

CardElevation used to resolve the elevation for this card in different states. This controls the size of the shadow below the card. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See also: Surface.

border: BorderStroke? = null

the border to draw around the container of this card

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this card. You can use this to change the card's appearance or preview the card in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable ColumnScope.() -> Unit

The content displayed on the card

CenterAlignedTopAppBar

@ExperimentalMaterial3Api
@Composable
fun CenterAlignedTopAppBar(
    title: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    navigationIcon: @Composable () -> Unit = {},
    actions: @Composable RowScope.() -> Unit = {},
    expandedHeight: Dp = TopAppBarDefaults.TopAppBarExpandedHeight,
    windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
    colors: TopAppBarColors = TopAppBarDefaults.centerAlignedTopAppBarColors(),
    scrollBehavior: TopAppBarScrollBehavior? = null
): Unit

Material Design center-aligned small top app bar.

Top app bars display information and actions at the top of a screen.

This small top app bar has a header title that is horizontally aligned to the center.

Center-aligned top app bar image

This CenterAlignedTopAppBar has slots for a title, navigation icon, and actions.

A center aligned top app bar that uses a scrollBehavior to customize its nested scrolling behavior when working in conjunction with a scrolling content looks like:

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp

Scaffold(
    topBar = {
        CenterAlignedTopAppBar(
            title = {
                Text("Centered TopAppBar", maxLines = 1, overflow = TextOverflow.Ellipsis)
            },
            navigationIcon = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Menu,
                        contentDescription = "Localized description"
                    )
                }
            },
            actions = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Favorite,
                        contentDescription = "Localized description"
                    )
                }
            }
        )
    },
    content = { innerPadding ->
        LazyColumn(
            contentPadding = innerPadding,
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            val list = (0..75).map { it.toString() }
            items(count = list.size) {
                Text(
                    text = list[it],
                    style = MaterialTheme.typography.bodyLarge,
                    modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                )
            }
        }
    }
)
Parameters
title: @Composable () -> Unit

the title to be displayed in the top app bar

modifier: Modifier = Modifier

the Modifier to be applied to this top app bar

navigationIcon: @Composable () -> Unit = {}

the navigation icon displayed at the start of the top app bar. This should typically be an IconButton or IconToggleButton.

actions: @Composable RowScope.() -> Unit = {}

the actions displayed at the end of the top app bar. This should typically be IconButtons. The default layout here is a Row, so icons inside will be placed horizontally.

expandedHeight: Dp = TopAppBarDefaults.TopAppBarExpandedHeight

this app bar's height. When a specified scrollBehavior causes the app bar to collapse or expand, this value will represent the maximum height that the bar will be allowed to expand. This value must be specified and finite, otherwise it will be ignored and replaced with TopAppBarDefaults.TopAppBarExpandedHeight.

windowInsets: WindowInsets = TopAppBarDefaults.windowInsets

a window insets that app bar will respect.

colors: TopAppBarColors = TopAppBarDefaults.centerAlignedTopAppBarColors()

TopAppBarColors that will be used to resolve the colors used for this top app bar in different states. See TopAppBarDefaults.centerAlignedTopAppBarColors.

scrollBehavior: TopAppBarScrollBehavior? = null

a TopAppBarScrollBehavior which holds various offset values that will be applied by this top app bar to set up its height and colors. A scroll behavior is designed to work in conjunction with a scrolled content to change the top app bar appearance as the content scrolls. See TopAppBarScrollBehavior.nestedScrollConnection.

Checkbox

@Composable
fun Checkbox(
    checked: Boolean,
    onCheckedChange: ((Boolean) -> Unit)?,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: CheckboxColors = CheckboxDefaults.colors(),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design checkbox.

Checkboxes allow users to select one or more items from a set. Checkboxes can turn an option on or off.

Checkbox image

Simple Checkbox sample:

import androidx.compose.material3.Checkbox
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

val checkedState = remember { mutableStateOf(true) }
Checkbox(checked = checkedState.value, onCheckedChange = { checkedState.value = it })

Combined Checkbox with Text sample:

import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.selection.toggleable
import androidx.compose.material3.Checkbox
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.dp

val (checkedState, onStateChange) = remember { mutableStateOf(true) }
Row(
    Modifier.fillMaxWidth()
        .height(56.dp)
        .toggleable(
            value = checkedState,
            onValueChange = { onStateChange(!checkedState) },
            role = Role.Checkbox
        )
        .padding(horizontal = 16.dp),
    verticalAlignment = Alignment.CenterVertically
) {
    Checkbox(
        checked = checkedState,
        onCheckedChange = null // null recommended for accessibility with screenreaders
    )
    Text(
        text = "Option selection",
        style = MaterialTheme.typography.bodyLarge,
        modifier = Modifier.padding(start = 16.dp)
    )
}
Parameters
checked: Boolean

whether this checkbox is checked or unchecked

onCheckedChange: ((Boolean) -> Unit)?

called when this checkbox is clicked. If null, then this checkbox will not be interactable, unless something else handles its input events and updates its state.

modifier: Modifier = Modifier

the Modifier to be applied to this checkbox

enabled: Boolean = true

controls the enabled state of this checkbox. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

colors: CheckboxColors = CheckboxDefaults.colors()

CheckboxColors that will be used to resolve the colors used for this checkbox in different states. See CheckboxDefaults.colors.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this checkbox. You can use this to change the checkbox's appearance or preview the checkbox in different states. Note that if null is provided, interactions will still happen internally.

See also
TriStateCheckbox

if you require support for an indeterminate state.

CircularProgressIndicator

@Composable
fun CircularProgressIndicator(
    modifier: Modifier = Modifier,
    color: Color = ProgressIndicatorDefaults.circularColor,
    strokeWidth: Dp = ProgressIndicatorDefaults.CircularStrokeWidth,
    trackColor: Color = ProgressIndicatorDefaults.circularIndeterminateTrackColor,
    strokeCap: StrokeCap = ProgressIndicatorDefaults.CircularIndeterminateStrokeCap,
    gapSize: Dp = ProgressIndicatorDefaults.CircularIndicatorTrackGapSize
): Unit

Indeterminate Material Design circular progress indicator.

Progress indicators express an unspecified wait time or display the duration of a process.

Circular progress indicator image

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.ui.Alignment

Column(horizontalAlignment = Alignment.CenterHorizontally) { CircularProgressIndicator() }
Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this progress indicator

color: Color = ProgressIndicatorDefaults.circularColor

color of this progress indicator

strokeWidth: Dp = ProgressIndicatorDefaults.CircularStrokeWidth

stroke width of this progress indicator

trackColor: Color = ProgressIndicatorDefaults.circularIndeterminateTrackColor

color of the track behind the indicator, visible when the progress has not reached the area of the overall indicator yet

strokeCap: StrokeCap = ProgressIndicatorDefaults.CircularIndeterminateStrokeCap

stroke cap to use for the ends of this progress indicator

gapSize: Dp = ProgressIndicatorDefaults.CircularIndicatorTrackGapSize

size of the gap between the progress indicator and the track

CircularProgressIndicator

@Composable
fun CircularProgressIndicator(
    progress: Float,
    modifier: Modifier = Modifier,
    color: Color = ProgressIndicatorDefaults.circularColor,
    strokeWidth: Dp = ProgressIndicatorDefaults.CircularStrokeWidth,
    trackColor: Color = ProgressIndicatorDefaults.circularTrackColor,
    strokeCap: StrokeCap = ProgressIndicatorDefaults.CircularDeterminateStrokeCap
): Unit

CircularProgressIndicator

@Composable
fun CircularProgressIndicator(
    progress: () -> Float,
    modifier: Modifier = Modifier,
    color: Color = ProgressIndicatorDefaults.circularColor,
    strokeWidth: Dp = ProgressIndicatorDefaults.CircularStrokeWidth,
    trackColor: Color = ProgressIndicatorDefaults.circularDeterminateTrackColor,
    strokeCap: StrokeCap = ProgressIndicatorDefaults.CircularDeterminateStrokeCap,
    gapSize: Dp = ProgressIndicatorDefaults.CircularIndicatorTrackGapSize
): Unit

Determinate Material Design circular progress indicator.

Progress indicators express an unspecified wait time or display the duration of a process.

Circular progress indicator image

By default there is no animation between progress values. You can use ProgressIndicatorDefaults.ProgressAnimationSpec as the default recommended AnimationSpec when animating progress, such as in the following example:

import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.width
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ProgressIndicatorDefaults
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

var progress by remember { mutableFloatStateOf(0.1f) }
val animatedProgress by
    animateFloatAsState(
        targetValue = progress,
        animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
    )

Column(horizontalAlignment = Alignment.CenterHorizontally) {
    CircularProgressIndicator(progress = { animatedProgress })
    Spacer(Modifier.requiredHeight(30.dp))
    Text("Set progress:")
    Slider(
        modifier = Modifier.width(300.dp),
        value = progress,
        valueRange = 0f..1f,
        onValueChange = { progress = it },
    )
}
Parameters
progress: () -> Float

the progress of this progress indicator, where 0.0 represents no progress and 1.0 represents full progress. Values outside of this range are coerced into the range.

modifier: Modifier = Modifier

the Modifier to be applied to this progress indicator

color: Color = ProgressIndicatorDefaults.circularColor

color of this progress indicator

strokeWidth: Dp = ProgressIndicatorDefaults.CircularStrokeWidth

stroke width of this progress indicator

trackColor: Color = ProgressIndicatorDefaults.circularDeterminateTrackColor

color of the track behind the indicator, visible when the progress has not reached the area of the overall indicator yet

strokeCap: StrokeCap = ProgressIndicatorDefaults.CircularDeterminateStrokeCap

stroke cap to use for the ends of this progress indicator

gapSize: Dp = ProgressIndicatorDefaults.CircularIndicatorTrackGapSize

size of the gap between the progress indicator and the track

CircularWavyProgressIndicator

@ExperimentalMaterial3ExpressiveApi
@Composable
fun CircularWavyProgressIndicator(
    modifier: Modifier = Modifier,
    color: Color = WavyProgressIndicatorDefaults.indicatorColor,
    trackColor: Color = WavyProgressIndicatorDefaults.trackColor,
    stroke: Stroke = WavyProgressIndicatorDefaults.circularIndicatorStroke,
    trackStroke: Stroke = WavyProgressIndicatorDefaults.circularTrackStroke,
    gapSize: Dp = WavyProgressIndicatorDefaults.CircularIndicatorTrackGapSize,
    amplitude: @FloatRange(from = 0.0, to = 1.0) Float = 1.0f,
    wavelength: Dp = WavyProgressIndicatorDefaults.CircularWavelength,
    waveSpeed: Dp = wavelength
): Unit

Indeterminate Material Design circular progress indicator.

Progress indicators express an unspecified wait time or display the duration of a process.

Indeterminate circular wavy progress indicator image

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.CircularWavyProgressIndicator
import androidx.compose.ui.Alignment

Column(horizontalAlignment = Alignment.CenterHorizontally) { CircularWavyProgressIndicator() }
Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this progress indicator

color: Color = WavyProgressIndicatorDefaults.indicatorColor

the progress indicator color

trackColor: Color = WavyProgressIndicatorDefaults.trackColor

the indicator's track color, visible when the progress has not reached the area of the overall indicator yet

stroke: Stroke = WavyProgressIndicatorDefaults.circularIndicatorStroke

a Stroke that will be used to draw this indicator

trackStroke: Stroke = WavyProgressIndicatorDefaults.circularTrackStroke

a Stroke that will be used to draw the indicator's track

gapSize: Dp = WavyProgressIndicatorDefaults.CircularIndicatorTrackGapSize

the gap between the track and the progress parts of the indicator

amplitude: @FloatRange(from = 0.0, to = 1.0) Float = 1.0f

the wave's amplitude. 0.0 represents no amplitude, and 1.0 represents an amplitude that will take the full height of the progress indicator. Values outside of this range are coerced into the range.

wavelength: Dp = WavyProgressIndicatorDefaults.CircularWavelength

the length of a wave in this circular indicator. Note that the actual wavelength may be different to ensure a continuous wave shape.

waveSpeed: Dp = wavelength

the speed in which the wave will move when the amplitude is greater than zero. The value here represents a DP per seconds, and by default it's matched to the wavelength to render an animation that moves the wave by one wave length per second. Note that the actual speed may be slightly different, as the wavelength can be adjusted to ensure a continuous wave shape.

CircularWavyProgressIndicator

@ExperimentalMaterial3ExpressiveApi
@Composable
fun CircularWavyProgressIndicator(
    progress: () -> Float,
    modifier: Modifier = Modifier,
    color: Color = WavyProgressIndicatorDefaults.indicatorColor,
    trackColor: Color = WavyProgressIndicatorDefaults.trackColor,
    stroke: Stroke = WavyProgressIndicatorDefaults.circularIndicatorStroke,
    trackStroke: Stroke = WavyProgressIndicatorDefaults.circularTrackStroke,
    gapSize: Dp = WavyProgressIndicatorDefaults.CircularIndicatorTrackGapSize,
    amplitude: (progress: Float) -> Float = WavyProgressIndicatorDefaults.indicatorAmplitude,
    wavelength: Dp = WavyProgressIndicatorDefaults.CircularWavelength,
    waveSpeed: Dp = wavelength
): Unit

Determinate Material Design circular progress indicator.

Progress indicators express an unspecified wait time or display the duration of a process.

Circular wavy progress indicator image

By default there is no animation between progress values. You can use ProgressIndicatorDefaults.ProgressAnimationSpec as the default recommended AnimationSpec when animating progress, such as in the following example:

import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.width
import androidx.compose.material3.CircularWavyProgressIndicator
import androidx.compose.material3.ProgressIndicatorDefaults
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

var progress by remember { mutableFloatStateOf(0.1f) }
val animatedProgress by
    animateFloatAsState(
        targetValue = progress,
        animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
    )

Column(horizontalAlignment = Alignment.CenterHorizontally) {
    CircularWavyProgressIndicator(progress = { animatedProgress })
    Spacer(Modifier.requiredHeight(30.dp))
    Text("Set progress:")
    Slider(
        modifier = Modifier.width(300.dp),
        value = progress,
        valueRange = 0f..1f,
        onValueChange = { progress = it },
    )
}

You may also follow the Material guidelines to create a thicker version of this indicator, like in this example:

import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material3.CircularWavyProgressIndicator
import androidx.compose.material3.ProgressIndicatorDefaults
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp

var progress by remember { mutableFloatStateOf(0.1f) }
val animatedProgress by
    animateFloatAsState(
        targetValue = progress,
        animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
    )
val thickStrokeWidth = with(LocalDensity.current) { 8.dp.toPx() }
val thickStroke =
    remember(thickStrokeWidth) { Stroke(width = thickStrokeWidth, cap = StrokeCap.Round) }
Column(horizontalAlignment = Alignment.CenterHorizontally) {
    CircularWavyProgressIndicator(
        progress = { animatedProgress },
        // Thick size is slightly larger than the
        // WavyProgressIndicatorDefaults.CircularContainerSize default
        modifier = Modifier.size(52.dp), // Thick size is slightly larger than the default
        stroke = thickStroke,
        trackStroke = thickStroke,
    )
    Spacer(Modifier.requiredHeight(30.dp))
    Text("Set progress:")
    Slider(
        modifier = Modifier.width(300.dp),
        value = progress,
        valueRange = 0f..1f,
        onValueChange = { progress = it },
    )
}
Parameters
progress: Float

the progress of this progress indicator, where 0.0 represents no progress and 1.0 represents full progress. Values outside of this range are coerced into the range.

modifier: Modifier = Modifier

the Modifier to be applied to this progress indicator

color: Color = WavyProgressIndicatorDefaults.indicatorColor

the progress indicator color

trackColor: Color = WavyProgressIndicatorDefaults.trackColor

the indicator's track color, visible when the progress has not reached the area of the overall indicator yet

stroke: Stroke = WavyProgressIndicatorDefaults.circularIndicatorStroke

a Stroke that will be used to draw this indicator

trackStroke: Stroke = WavyProgressIndicatorDefaults.circularTrackStroke

a Stroke that will be used to draw the indicator's track

gapSize: Dp = WavyProgressIndicatorDefaults.CircularIndicatorTrackGapSize

the gap between the track and the progress parts of the indicator

amplitude: (progress: Float) -> Float = WavyProgressIndicatorDefaults.indicatorAmplitude

a lambda that provides an amplitude for the wave path as a function of the indicator's progress. 0.0 represents no amplitude, and 1.0 represents a max amplitude. Values outside of this range are coerced into the range.

wavelength: Dp = WavyProgressIndicatorDefaults.CircularWavelength

the length of a wave in this circular indicator. Note that the actual wavelength may be different to ensure a continuous wave shape.

waveSpeed: Dp = wavelength

the speed in which the wave will move when the amplitude is greater than zero. The value here represents a DP per seconds, and by default it's matched to the wavelength to render an animation that moves the wave by one wave length per second. Note that the actual speed may be slightly different, as the wavelength can be adjusted to ensure a continuous wave shape.

ContainedLoadingIndicator

@ExperimentalMaterial3ExpressiveApi
@Composable
fun ContainedLoadingIndicator(
    modifier: Modifier = Modifier,
    containerColor: Color = LoadingIndicatorDefaults.containedContainerColor,
    indicatorColor: Color = LoadingIndicatorDefaults.containedIndicatorColor,
    containerShape: Shape = LoadingIndicatorDefaults.containerShape,
    polygons: List<RoundedPolygon> = LoadingIndicatorDefaults.IndeterminateIndicatorPolygons
): Unit

A Material Design contained loading indicator.

This version of the loading indicator animates and morphs between various shapes as long as the loading indicator is visible. The shapes in this variation are contained within a colored containerShape.

Contained loading indicator image

It can be created like this:

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.ContainedLoadingIndicator
import androidx.compose.material3.LoadingIndicator
import androidx.compose.ui.Alignment

Column(horizontalAlignment = Alignment.CenterHorizontally) { ContainedLoadingIndicator() }
Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this loading indicator

containerColor: Color = LoadingIndicatorDefaults.containedContainerColor

the loading indicator's container color

indicatorColor: Color = LoadingIndicatorDefaults.containedIndicatorColor

the loading indicator's color

containerShape: Shape = LoadingIndicatorDefaults.containerShape

the loading indicator's container shape

polygons: List<RoundedPolygon> = LoadingIndicatorDefaults.IndeterminateIndicatorPolygons

a list of RoundedPolygons for the sequence of shapes this loading indicator will morph between. The loading indicator expects at least two items in that list.

Throws
kotlin.IllegalArgumentException

if the polygons list holds less than two items

ContainedLoadingIndicator

@ExperimentalMaterial3ExpressiveApi
@Composable
fun ContainedLoadingIndicator(
    progress: () -> Float,
    modifier: Modifier = Modifier,
    containerColor: Color = LoadingIndicatorDefaults.containedContainerColor,
    indicatorColor: Color = LoadingIndicatorDefaults.containedIndicatorColor,
    containerShape: Shape = LoadingIndicatorDefaults.containerShape,
    polygons: List<RoundedPolygon> = LoadingIndicatorDefaults.DeterminateIndicatorPolygons
): Unit

A Material Design contained loading indicator.

This version of the loading indicator morphs between its polygons shapes by the value of its progress. The shapes in this variation are contained within a colored containerShape.

Contained loading indicator image

It can be created like this:

import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.spring
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.width
import androidx.compose.material3.ContainedLoadingIndicator
import androidx.compose.material3.LoadingIndicator
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

var progress by remember { mutableFloatStateOf(0f) }
val animatedProgress by
    animateFloatAsState(
        targetValue = progress,
        animationSpec =
            spring(
                dampingRatio = Spring.DampingRatioNoBouncy,
                stiffness = Spring.StiffnessVeryLow,
                visibilityThreshold = 1 / 1000f
            )
    )

Column(horizontalAlignment = Alignment.CenterHorizontally) {
    ContainedLoadingIndicator(progress = { animatedProgress })
    Spacer(Modifier.requiredHeight(30.dp))
    Text("Set loading progress:")
    Slider(
        modifier = Modifier.width(300.dp),
        value = progress,
        valueRange = 0f..1f,
        onValueChange = { progress = it },
    )
}

It can also be used as an indicator for a PullToRefreshBox like this:

import androidx.compose.animation.core.LinearOutSlowInEasing
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem
import androidx.compose.material3.LoadingIndicator
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults
import androidx.compose.material3.pulltorefresh.pullToRefresh
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer

var itemCount by remember { mutableStateOf(15) }
var isRefreshing by remember { mutableStateOf(false) }
val state = rememberPullToRefreshState()
val coroutineScope = rememberCoroutineScope()
val onRefresh: () -> Unit = {
    isRefreshing = true
    coroutineScope.launch {
        // fetch something
        delay(5000)
        itemCount += 5
        isRefreshing = false
    }
}

val scaleFraction = {
    if (isRefreshing) 1f
    else LinearOutSlowInEasing.transform(state.distanceFraction).coerceIn(0f, 1f)
}

Scaffold(
    modifier =
        Modifier.pullToRefresh(
            state = state,
            isRefreshing = isRefreshing,
            onRefresh = onRefresh
        ),
    topBar = {
        TopAppBar(
            title = { Text("TopAppBar") },
            // Provide an accessible alternative to trigger refresh.
            actions = {
                IconButton(onClick = onRefresh) {
                    Icon(Icons.Filled.Refresh, "Trigger Refresh")
                }
            }
        )
    }
) {
    Box(Modifier.padding(it)) {
        LazyColumn(Modifier.fillMaxSize()) {
            if (!isRefreshing) {
                items(itemCount) { ListItem({ Text(text = "Item ${itemCount - it}") }) }
            }
        }
        Box(
            Modifier.align(Alignment.TopCenter).graphicsLayer {
                scaleX = scaleFraction()
                scaleY = scaleFraction()
            }
        ) {
            PullToRefreshDefaults.LoadingIndicator(state = state, isRefreshing = isRefreshing)
        }
    }
}
Parameters
progress: () -> Float

the progress of this loading indicator, where 0.0 represents no progress and 1.0 represents full progress. Values outside of this range are coerced into the range. The indicator will morph its shapes between the provided polygons according to the value of the progress.

modifier: Modifier = Modifier

the Modifier to be applied to this loading indicator

containerColor: Color = LoadingIndicatorDefaults.containedContainerColor

the loading indicator's container color

indicatorColor: Color = LoadingIndicatorDefaults.containedIndicatorColor

the loading indicator's color

containerShape: Shape = LoadingIndicatorDefaults.containerShape

the loading indicator's container shape

polygons: List<RoundedPolygon> = LoadingIndicatorDefaults.DeterminateIndicatorPolygons

a list of RoundedPolygons for the sequence of shapes this loading indicator will morph between as it progresses from 0.0 to 1.0. The loading indicator expects at least two items in that list.

Throws
kotlin.IllegalArgumentException

if the polygons list holds less than two items

@ExperimentalMaterial3Api
@Composable
fun DatePicker(
    state: DatePickerState,
    modifier: Modifier = Modifier,
    dateFormatter: DatePickerFormatter = remember { DatePickerDefaults.dateFormatter() },
    colors: DatePickerColors = DatePickerDefaults.colors(),
    title: (@Composable () -> Unit)? = { DatePickerDefaults.DatePickerTitle( displayMode = state.displayMode, modifier = Modifier.padding(DatePickerTitlePadding), contentColor = colors.titleContentColor ) },
    headline: (@Composable () -> Unit)? = { DatePickerDefaults.DatePickerHeadline( selectedDateMillis = state.selectedDateMillis, displayMode = state.displayMode, dateFormatter = dateFormatter, modifier = Modifier.padding(DatePickerHeadlinePadding), contentColor = colors.headlineContentColor ) },
    showModeToggle: Boolean = true,
    requestFocus: Boolean = true
): Unit

Material Design date picker.

Date pickers let people select a date and preferably should be embedded into Dialogs. See DatePickerDialog.

By default, a date picker lets you pick a date via a calendar UI. However, it also allows switching into a date input mode for a manual entry of dates using the numbers on a keyboard.

Date picker image

A simple DatePicker looks like:

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.DatePicker
import androidx.compose.material3.DatePickerState
import androidx.compose.material3.Text
import androidx.compose.material3.rememberDatePickerState
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

Column(
    modifier = Modifier.verticalScroll(rememberScrollState()),
    verticalArrangement = Arrangement.spacedBy(8.dp)
) {
    // Pre-select a date for January 4, 2020
    val datePickerState = rememberDatePickerState(initialSelectedDateMillis = 1578096000000)
    DatePicker(state = datePickerState, modifier = Modifier.padding(16.dp))

    Text(
        "Selected date timestamp: ${datePickerState.selectedDateMillis ?: "no selection"}",
        modifier = Modifier.align(Alignment.CenterHorizontally)
    )
}

A DatePicker with an initial UI of a date input mode looks like:

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.DatePicker
import androidx.compose.material3.DatePickerState
import androidx.compose.material3.DisplayMode
import androidx.compose.material3.Text
import androidx.compose.material3.rememberDatePickerState
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
    val state = rememberDatePickerState(initialDisplayMode = DisplayMode.Input)
    DatePicker(state = state, modifier = Modifier.padding(16.dp))

    Text(
        "Entered date timestamp: ${state.selectedDateMillis ?: "no input"}",
        modifier = Modifier.align(Alignment.CenterHorizontally)
    )
}

A DatePicker with a provided SelectableDates that blocks certain days from being selected looks like:

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.DatePicker
import androidx.compose.material3.DatePickerState
import androidx.compose.material3.SelectableDates
import androidx.compose.material3.Text
import androidx.compose.material3.rememberDatePickerState
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val datePickerState =
    rememberDatePickerState(
        selectableDates =
            object : SelectableDates {
                // Blocks Sunday and Saturday from being selected.
                override fun isSelectableDate(utcTimeMillis: Long): Boolean {
                    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                        val dayOfWeek =
                            Instant.ofEpochMilli(utcTimeMillis)
                                .atZone(ZoneId.of("UTC"))
                                .toLocalDate()
                                .dayOfWeek
                        dayOfWeek != DayOfWeek.SUNDAY && dayOfWeek != DayOfWeek.SATURDAY
                    } else {
                        val calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
                        calendar.timeInMillis = utcTimeMillis
                        calendar[Calendar.DAY_OF_WEEK] != Calendar.SUNDAY &&
                            calendar[Calendar.DAY_OF_WEEK] != Calendar.SATURDAY
                    }
                }

                // Allow selecting dates from year 2023 forward.
                override fun isSelectableYear(year: Int): Boolean {
                    return year > 2022
                }
            }
    )

Column(
    modifier = Modifier.verticalScroll(rememberScrollState()),
    verticalArrangement = Arrangement.spacedBy(8.dp)
) {
    DatePicker(state = datePickerState)
    Text(
        "Selected date timestamp: ${datePickerState.selectedDateMillis ?: "no selection"}",
        modifier = Modifier.align(Alignment.CenterHorizontally)
    )
}
Parameters
state: DatePickerState

state of the date picker. See rememberDatePickerState.

modifier: Modifier = Modifier

the Modifier to be applied to this date picker

dateFormatter: DatePickerFormatter = remember { DatePickerDefaults.dateFormatter() }

a DatePickerFormatter that provides formatting skeletons for dates display

colors: DatePickerColors = DatePickerDefaults.colors()

DatePickerColors that will be used to resolve the colors used for this date picker in different states. See DatePickerDefaults.colors.

title: (@Composable () -> Unit)? = { DatePickerDefaults.DatePickerTitle( displayMode = state.displayMode, modifier = Modifier.padding(DatePickerTitlePadding), contentColor = colors.titleContentColor ) }

the title to be displayed in the date picker

headline: (@Composable () -> Unit)? = { DatePickerDefaults.DatePickerHeadline( selectedDateMillis = state.selectedDateMillis, displayMode = state.displayMode, dateFormatter = dateFormatter, modifier = Modifier.padding(DatePickerHeadlinePadding), contentColor = colors.headlineContentColor ) }

the headline to be displayed in the date picker

showModeToggle: Boolean = true

indicates if this DatePicker should show a mode toggle action that transforms it into a date input

requestFocus: Boolean = true

have a focus request be sent to the text field when the date picker is in an input mode

DatePickerDialog

@ExperimentalMaterial3Api
@Composable
fun DatePickerDialog(
    onDismissRequest: () -> Unit,
    confirmButton: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    dismissButton: (@Composable () -> Unit)? = null,
    shape: Shape = DatePickerDefaults.shape,
    tonalElevation: Dp = DatePickerDefaults.TonalElevation,
    colors: DatePickerColors = DatePickerDefaults.colors(),
    properties: DialogProperties = DialogProperties(usePlatformDefaultWidth = false),
    content: @Composable ColumnScope.() -> Unit
): Unit

Material Design date picker dialog.

A dialog for displaying a DatePicker. Date pickers let people select a date.

A sample for displaying a DatePicker in a dialog:

import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.DatePicker
import androidx.compose.material3.DatePickerDialog
import androidx.compose.material3.DatePickerState
import androidx.compose.material3.DisplayMode
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.rememberDatePickerState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier

// Decoupled snackbar host state from scaffold state for demo purposes.
val snackState = remember { SnackbarHostState() }
val snackScope = rememberCoroutineScope()
SnackbarHost(hostState = snackState, Modifier)
val openDialog = remember { mutableStateOf(true) }
// TODO demo how to read the selected date from the state.
if (openDialog.value) {
    val datePickerState = rememberDatePickerState()
    val confirmEnabled = remember {
        derivedStateOf { datePickerState.selectedDateMillis != null }
    }
    DatePickerDialog(
        onDismissRequest = {
            // Dismiss the dialog when the user clicks outside the dialog or on the back
            // button. If you want to disable that functionality, simply use an empty
            // onDismissRequest.
            openDialog.value = false
        },
        confirmButton = {
            TextButton(
                onClick = {
                    openDialog.value = false
                    snackScope.launch {
                        snackState.showSnackbar(
                            "Selected date timestamp: ${datePickerState.selectedDateMillis}"
                        )
                    }
                },
                enabled = confirmEnabled.value
            ) {
                Text("OK")
            }
        },
        dismissButton = {
            TextButton(onClick = { openDialog.value = false }) { Text("Cancel") }
        }
    ) {
        // The verticalScroll will allow scrolling to show the entire month in case there is not
        // enough horizontal space (for example, when in landscape mode).
        // Note that it's still currently recommended to use a DisplayMode.Input at the state in
        // those cases.
        DatePicker(
            state = datePickerState,
            modifier = Modifier.verticalScroll(rememberScrollState())
        )
    }
}
Parameters
onDismissRequest: () -> Unit

called when the user tries to dismiss the Dialog by clicking outside or pressing the back button. This is not called when the dismiss button is clicked.

confirmButton: @Composable () -> Unit

button which is meant to confirm a proposed action, thus resolving what triggered the dialog. The dialog does not set up any events for this button, nor does it control its enablement, so those need to be set up by the caller.

modifier: Modifier = Modifier

the Modifier to be applied to this dialog's content.

dismissButton: (@Composable () -> Unit)? = null

button which is meant to dismiss the dialog. The dialog does not set up any events for this button so they need to be set up by the caller.

shape: Shape = DatePickerDefaults.shape

defines the dialog's surface shape as well its shadow

tonalElevation: Dp = DatePickerDefaults.TonalElevation

when DatePickerColors.containerColor is ColorScheme.surface, a higher the elevation will result in a darker color in light theme and lighter color in dark theme

colors: DatePickerColors = DatePickerDefaults.colors()

DatePickerColors that will be used to resolve the colors used for this date picker in different states. See DatePickerDefaults.colors.

properties: DialogProperties = DialogProperties(usePlatformDefaultWidth = false)

typically platform specific properties to further configure the dialog

content: @Composable ColumnScope.() -> Unit

the content of the dialog (i.e. a DatePicker, for example)

DatePickerState

@ExperimentalMaterial3Api
fun DatePickerState(
    locale: CalendarLocale,
    initialSelectedDateMillis: Long? = null,
    initialDisplayedMonthMillis: Long? = initialSelectedDateMillis,
    yearRange: IntRange = DatePickerDefaults.YearRange,
    initialDisplayMode: DisplayMode = DisplayMode.Picker,
    selectableDates: SelectableDates = DatePickerDefaults.AllDates
): DatePickerState

Creates a DatePickerState.

For most cases, you are advised to use the rememberDatePickerState when in a composition.

Note that in case you provide a locale that is different than the default platform locale, you may need to ensure that the picker's title and headline localized correctly. The following sample shows one possible way of doing so by applying a local composition of a LocalContext and LocaleConfiguration.

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.DatePicker
import androidx.compose.material3.DatePickerState
import androidx.compose.material3.Text
import androidx.compose.material3.rememberDatePickerState
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp

val preferredLocales = LocaleList.forLanguageTags("HE")
val config = Configuration()
config.setLocales(preferredLocales)
val newContext = LocalContext.current.createConfigurationContext(config)
CompositionLocalProvider(
    LocalContext provides newContext,
    LocalConfiguration provides config,
    LocalLayoutDirection provides LayoutDirection.Rtl
) {
    Column(
        modifier = Modifier.verticalScroll(rememberScrollState()),
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        // Pre-select a date for January 4, 2020
        // Initialize date picker with the preferred locale. Here we create a state directly,
        // but since the Locale was set at the CompositionLocalProvider through a Configuration,
        // a `val datePickerState = rememberDatePickerState(...)` will have the same effect.
        val datePickerState = remember {
            DatePickerState(
                initialSelectedDateMillis = 1578096000000,
                // Set to "HE" locale.
                locale = preferredLocales.get(0)
            )
        }
        DatePicker(state = datePickerState, modifier = Modifier.padding(16.dp))

        Text(
            "Selected date timestamp: ${datePickerState.selectedDateMillis ?: "no selection"}",
            modifier = Modifier.align(Alignment.CenterHorizontally)
        )
    }
}
Parameters
locale: CalendarLocale

the CalendarLocale that will be used when formatting dates, determining the input format, displaying the week-day, determining the first day of the week, and more. Note that in case the provided CalendarLocale differs from the platform's default Locale, you may need to ensure that the picker's title and headline localized correctly, and in some cases, you may need to apply an RTL layout.

initialSelectedDateMillis: Long? = null

timestamp in UTC milliseconds from the epoch that represents an initial selection of a date. Provide a null to indicate no selection. Note that the state's DatePickerState.selectedDateMillis will provide a timestamp that represents the start of the day, which may be different than the provided initialSelectedDateMillis.

initialDisplayedMonthMillis: Long? = initialSelectedDateMillis

timestamp in UTC milliseconds from the epoch that represents an initial selection of a month to be displayed to the user. In case null is provided, the displayed month would be the current one.

yearRange: IntRange = DatePickerDefaults.YearRange

an IntRange that holds the year range that the date picker will be limited to

initialDisplayMode: DisplayMode = DisplayMode.Picker

an initial DisplayMode that this state will hold

selectableDates: SelectableDates = DatePickerDefaults.AllDates

a SelectableDates that is consulted to check if a date is allowed. In case a date is not allowed to be selected, it will appear disabled in the UI.

Throws
kotlin.IllegalArgumentException

if the initial selected date or displayed month represent a year that is out of the year range.

DateRangePicker

@ExperimentalMaterial3Api
@Composable
fun DateRangePicker(
    state: DateRangePickerState,
    modifier: Modifier = Modifier,
    dateFormatter: DatePickerFormatter = remember { DatePickerDefaults.dateFormatter() },
    colors: DatePickerColors = DatePickerDefaults.colors(),
    title: (@Composable () -> Unit)? = { DateRangePickerDefaults.DateRangePickerTitle( displayMode = state.displayMode, modifier = Modifier.padding(DateRangePickerTitlePadding), contentColor = colors.titleContentColor ) },
    headline: (@Composable () -> Unit)? = { DateRangePickerDefaults.DateRangePickerHeadline( selectedStartDateMillis = state.selectedStartDateMillis, selectedEndDateMillis = state.selectedEndDateMillis, displayMode = state.displayMode, dateFormatter, modifier = Modifier.padding(DateRangePickerHeadlinePadding), contentColor = colors.headlineContentColor ) },
    showModeToggle: Boolean = true,
    requestFocus: Boolean = true
): Unit

Material Design date range picker.

Date range pickers let people select a range of dates and can be embedded into Dialogs.

Date range picker image

A simple DateRangePicker looks like:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Icon
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.DatePicker
import androidx.compose.material3.DatePickerDefaults
import androidx.compose.material3.DateRangePicker
import androidx.compose.material3.IconButton
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.rememberDateRangePickerState
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex

// Decoupled snackbar host state from scaffold state for demo purposes.
val snackState = remember { SnackbarHostState() }
val snackScope = rememberCoroutineScope()
SnackbarHost(hostState = snackState, Modifier.zIndex(1f))

val state = rememberDateRangePickerState()
Column(modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Top) {
    // Add a row with "Save" and dismiss actions.
    Row(
        modifier =
            Modifier.fillMaxWidth()
                .background(DatePickerDefaults.colors().containerColor)
                .padding(start = 12.dp, end = 12.dp),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.SpaceBetween
    ) {
        IconButton(onClick = { /* dismiss the UI */ }) {
            Icon(Icons.Filled.Close, contentDescription = "Localized description")
        }
        TextButton(
            onClick = {
                snackScope.launch {
                    val range = state.selectedStartDateMillis!!..state.selectedEndDateMillis!!
                    snackState.showSnackbar("Saved range (timestamps): $range")
                }
            },
            enabled = state.selectedEndDateMillis != null
        ) {
            Text(text = "Save")
        }
    }
    DateRangePicker(state = state, modifier = Modifier.weight(1f))
}
Parameters
state: DateRangePickerState

state of the date range picker. See rememberDateRangePickerState.

modifier: Modifier = Modifier

the Modifier to be applied to this date range picker

dateFormatter: DatePickerFormatter = remember { DatePickerDefaults.dateFormatter() }

a DatePickerFormatter that provides formatting skeletons for dates display

colors: DatePickerColors = DatePickerDefaults.colors()

DatePickerColors that will be used to resolve the colors used for this date range picker in different states. See DatePickerDefaults.colors.

title: (@Composable () -> Unit)? = { DateRangePickerDefaults.DateRangePickerTitle( displayMode = state.displayMode, modifier = Modifier.padding(DateRangePickerTitlePadding), contentColor = colors.titleContentColor ) }

the title to be displayed in the date range picker

headline: (@Composable () -> Unit)? = { DateRangePickerDefaults.DateRangePickerHeadline( selectedStartDateMillis = state.selectedStartDateMillis, selectedEndDateMillis = state.selectedEndDateMillis, displayMode = state.displayMode, dateFormatter, modifier = Modifier.padding(DateRangePickerHeadlinePadding), contentColor = colors.headlineContentColor ) }

the headline to be displayed in the date range picker

showModeToggle: Boolean = true

indicates if this DateRangePicker should show a mode toggle action that transforms it into a date range input

requestFocus: Boolean = true

have a focus request be sent to the text field when the date picker is in an input mode

DateRangePickerState

@ExperimentalMaterial3Api
fun DateRangePickerState(
    locale: CalendarLocale,
    initialSelectedStartDateMillis: Long? = null,
    initialSelectedEndDateMillis: Long? = null,
    initialDisplayedMonthMillis: Long? = initialSelectedStartDateMillis,
    yearRange: IntRange = DatePickerDefaults.YearRange,
    initialDisplayMode: DisplayMode = DisplayMode.Picker,
    selectableDates: SelectableDates = DatePickerDefaults.AllDates
): DateRangePickerState

Creates a DateRangePickerState.

For most cases, you are advised to use the rememberDateRangePickerState when in a composition.

Note that in case you provide a locale that is different than the default platform locale, you may need to ensure that the picker's title and headline localized correctly. The following sample shows one possible way of doing so by applying a local composition of a LocalContext and LocaleConfiguration.

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.DatePicker
import androidx.compose.material3.DatePickerState
import androidx.compose.material3.Text
import androidx.compose.material3.rememberDatePickerState
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp

val preferredLocales = LocaleList.forLanguageTags("HE")
val config = Configuration()
config.setLocales(preferredLocales)
val newContext = LocalContext.current.createConfigurationContext(config)
CompositionLocalProvider(
    LocalContext provides newContext,
    LocalConfiguration provides config,
    LocalLayoutDirection provides LayoutDirection.Rtl
) {
    Column(
        modifier = Modifier.verticalScroll(rememberScrollState()),
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        // Pre-select a date for January 4, 2020
        // Initialize date picker with the preferred locale. Here we create a state directly,
        // but since the Locale was set at the CompositionLocalProvider through a Configuration,
        // a `val datePickerState = rememberDatePickerState(...)` will have the same effect.
        val datePickerState = remember {
            DatePickerState(
                initialSelectedDateMillis = 1578096000000,
                // Set to "HE" locale.
                locale = preferredLocales.get(0)
            )
        }
        DatePicker(state = datePickerState, modifier = Modifier.padding(16.dp))

        Text(
            "Selected date timestamp: ${datePickerState.selectedDateMillis ?: "no selection"}",
            modifier = Modifier.align(Alignment.CenterHorizontally)
        )
    }
}
Parameters
locale: CalendarLocale

the CalendarLocale that will be used when formatting dates, determining the input format, displaying the week-day, determining the first day of the week, and more. Note that in case the provided CalendarLocale differs from the platform's default Locale, you may need to ensure that the picker's title and headline localized correctly, and in some cases, you may need to apply an RTL layout.

initialSelectedStartDateMillis: Long? = null

timestamp in UTC milliseconds from the epoch that represents an initial selection of a start date. Provide a null to indicate no selection.

initialSelectedEndDateMillis: Long? = null

timestamp in UTC milliseconds from the epoch that represents an initial selection of an end date. Provide a null to indicate no selection.

initialDisplayedMonthMillis: Long? = initialSelectedStartDateMillis

timestamp in UTC milliseconds from the epoch that represents an initial selection of a month to be displayed to the user. By default, in case an initialSelectedStartDateMillis is provided, the initial displayed month would be the month of the selected date. Otherwise, in case null is provided, the displayed month would be the current one.

yearRange: IntRange = DatePickerDefaults.YearRange

an IntRange that holds the year range that the date picker will be limited to

initialDisplayMode: DisplayMode = DisplayMode.Picker

an initial DisplayMode that this state will hold

selectableDates: SelectableDates = DatePickerDefaults.AllDates

a SelectableDates that is consulted to check if a date is allowed. In case a date is not allowed to be selected, it will appear disabled in the UI

Throws
kotlin.IllegalArgumentException

if the initial timestamps do not fall within the year range this state is created with, or the end date precedes the start date, or when an end date is provided without a start date (e.g. the start date was null, while the end date was not).

DismissibleDrawerSheet

@Composable
fun DismissibleDrawerSheet(
    modifier: Modifier = Modifier,
    drawerShape: Shape = RectangleShape,
    drawerContainerColor: Color = DrawerDefaults.standardContainerColor,
    drawerContentColor: Color = contentColorFor(drawerContainerColor),
    drawerTonalElevation: Dp = DrawerDefaults.DismissibleDrawerElevation,
    windowInsets: WindowInsets = DrawerDefaults.windowInsets,
    content: @Composable ColumnScope.() -> Unit
): Unit

Content inside of a dismissible navigation drawer.

Note: This version of DismissibleDrawerSheet does not handle back by default. For automatic back handling and predictive back animations on Android 14+, use the DismissibleDrawerSheet that accepts drawerState as a param.

Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this drawer's content

drawerShape: Shape = RectangleShape

defines the shape of this drawer's container

drawerContainerColor: Color = DrawerDefaults.standardContainerColor

the color used for the background of this drawer. Use Color.Transparent to have no color.

drawerContentColor: Color = contentColorFor(drawerContainerColor)

the preferred color for content inside this drawer. Defaults to either the matching content color for drawerContainerColor, or to the current LocalContentColor if drawerContainerColor is not a color from the theme.

drawerTonalElevation: Dp = DrawerDefaults.DismissibleDrawerElevation

when drawerContainerColor is ColorScheme.surface, a translucent primary color overlay is applied on top of the container. A higher tonal elevation value will result in a darker color in light theme and lighter color in dark theme. See also: Surface.

windowInsets: WindowInsets = DrawerDefaults.windowInsets

a window insets for the sheet.

content: @Composable ColumnScope.() -> Unit

content inside of a dismissible navigation drawer

DismissibleDrawerSheet

@Composable
fun DismissibleDrawerSheet(
    drawerState: DrawerState,
    modifier: Modifier = Modifier,
    drawerShape: Shape = RectangleShape,
    drawerContainerColor: Color = DrawerDefaults.standardContainerColor,
    drawerContentColor: Color = contentColorFor(drawerContainerColor),
    drawerTonalElevation: Dp = DrawerDefaults.DismissibleDrawerElevation,
    windowInsets: WindowInsets = DrawerDefaults.windowInsets,
    content: @Composable ColumnScope.() -> Unit
): Unit

Content inside of a dismissible navigation drawer.

Note: This version of DismissibleDrawerSheet requires a drawerState to be provided and will handle back by default for all Android versions, as well as animate during predictive back on Android 14+.

Parameters
drawerState: DrawerState

state of the drawer

modifier: Modifier = Modifier

the Modifier to be applied to this drawer's content

drawerShape: Shape = RectangleShape

defines the shape of this drawer's container

drawerContainerColor: Color = DrawerDefaults.standardContainerColor

the color used for the background of this drawer. Use Color.Transparent to have no color.

drawerContentColor: Color = contentColorFor(drawerContainerColor)

the preferred color for content inside this drawer. Defaults to either the matching content color for drawerContainerColor, or to the current LocalContentColor if drawerContainerColor is not a color from the theme.

drawerTonalElevation: Dp = DrawerDefaults.DismissibleDrawerElevation

when drawerContainerColor is ColorScheme.surface, a translucent primary color overlay is applied on top of the container. A higher tonal elevation value will result in a darker color in light theme and lighter color in dark theme. See also: Surface.

windowInsets: WindowInsets = DrawerDefaults.windowInsets

a window insets for the sheet.

content: @Composable ColumnScope.() -> Unit

content inside of a dismissible navigation drawer

DismissibleNavigationDrawer

@Composable
fun DismissibleNavigationDrawer(
    drawerContent: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    drawerState: DrawerState = rememberDrawerState(DrawerValue.Closed),
    gesturesEnabled: Boolean = true,
    content: @Composable () -> Unit
): Unit

Material Design navigation drawer.

Navigation drawers provide ergonomic access to destinations in an app. They’re often next to app content and affect the screen’s layout grid.

Navigation drawer image

Dismissible standard drawers can be used for layouts that prioritize content (such as a photo gallery) or for apps where users are unlikely to switch destinations often. They should use a visible navigation menu icon to open and close the drawer.

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material.icons.filled.Bookmarks
import androidx.compose.material.icons.filled.CalendarMonth
import androidx.compose.material.icons.filled.Dashboard
import androidx.compose.material.icons.filled.Email
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Group
import androidx.compose.material.icons.filled.Headphones
import androidx.compose.material.icons.filled.Image
import androidx.compose.material.icons.filled.JoinFull
import androidx.compose.material.icons.filled.Keyboard
import androidx.compose.material.icons.filled.Laptop
import androidx.compose.material.icons.filled.Map
import androidx.compose.material.icons.filled.Navigation
import androidx.compose.material.icons.filled.Outbox
import androidx.compose.material.icons.filled.PushPin
import androidx.compose.material.icons.filled.QrCode
import androidx.compose.material.icons.filled.Radio
import androidx.compose.material3.Button
import androidx.compose.material3.DismissibleDrawerSheet
import androidx.compose.material3.DismissibleNavigationDrawer
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationDrawerItem
import androidx.compose.material3.Text
import androidx.compose.material3.rememberDrawerState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val drawerState = rememberDrawerState(DrawerValue.Closed)
val scope = rememberCoroutineScope()
// icons to mimic drawer destinations
val items =
    listOf(
        Icons.Default.AccountCircle,
        Icons.Default.Bookmarks,
        Icons.Default.CalendarMonth,
        Icons.Default.Dashboard,
        Icons.Default.Email,
        Icons.Default.Favorite,
        Icons.Default.Group,
        Icons.Default.Headphones,
        Icons.Default.Image,
        Icons.Default.JoinFull,
        Icons.Default.Keyboard,
        Icons.Default.Laptop,
        Icons.Default.Map,
        Icons.Default.Navigation,
        Icons.Default.Outbox,
        Icons.Default.PushPin,
        Icons.Default.QrCode,
        Icons.Default.Radio,
    )
val selectedItem = remember { mutableStateOf(items[0]) }

DismissibleNavigationDrawer(
    drawerState = drawerState,
    drawerContent = {
        DismissibleDrawerSheet(drawerState) {
            Column(Modifier.verticalScroll(rememberScrollState())) {
                Spacer(Modifier.height(12.dp))
                items.forEach { item ->
                    NavigationDrawerItem(
                        icon = { Icon(item, contentDescription = null) },
                        label = { Text(item.name.substringAfterLast(".")) },
                        selected = item == selectedItem.value,
                        onClick = {
                            scope.launch { drawerState.close() }
                            selectedItem.value = item
                        },
                        modifier = Modifier.padding(horizontal = 12.dp)
                    )
                }
            }
        }
    },
    content = {
        Column(
            modifier = Modifier.fillMaxSize().padding(16.dp),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text(text = if (drawerState.isClosed) ">>> Swipe >>>" else "<<< Swipe <<<")
            Spacer(Modifier.height(20.dp))
            Button(onClick = { scope.launch { drawerState.open() } }) { Text("Click to open") }
        }
    }
)
Parameters
drawerContent: @Composable () -> Unit

content inside this drawer

modifier: Modifier = Modifier

the Modifier to be applied to this drawer

drawerState: DrawerState = rememberDrawerState(DrawerValue.Closed)

state of the drawer

gesturesEnabled: Boolean = true

whether or not the drawer can be interacted by gestures

content: @Composable () -> Unit

content of the rest of the UI

@Composable
fun Divider(
    modifier: Modifier = Modifier,
    thickness: Dp = DividerDefaults.Thickness,
    color: Color = DividerDefaults.color
): Unit

DockedSearchBar

@ExperimentalMaterial3Api
@Composable
fun DockedSearchBar(
    inputField: @Composable () -> Unit,
    expanded: Boolean,
    onExpandedChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    shape: Shape = SearchBarDefaults.dockedShape,
    colors: SearchBarColors = SearchBarDefaults.colors(),
    tonalElevation: Dp = SearchBarDefaults.TonalElevation,
    shadowElevation: Dp = SearchBarDefaults.ShadowElevation,
    content: @Composable ColumnScope.() -> Unit
): Unit

Material Design search.

A search bar represents a floating search field that allows users to enter a keyword or phrase and get relevant information. It can be used as a way to navigate through an app via search queries.

An search bar expands into a search "view" and can be used to display dynamic suggestions or search results.

Search bar image

A DockedSearchBar displays search results in a bounded table below the input field. It is an alternative to SearchBar when expanding to full-screen size is undesirable on large screens such as tablets.

An example looks like:

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.filled.Star
import androidx.compose.material3.DockedSearchBar
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.ListItemDefaults
import androidx.compose.material3.SearchBar
import androidx.compose.material3.SearchBarDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.semantics.isTraversalGroup
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.traversalIndex
import androidx.compose.ui.unit.dp

val textFieldState = rememberTextFieldState()
var expanded by rememberSaveable { mutableStateOf(false) }

Box(Modifier.fillMaxSize().semantics { isTraversalGroup = true }) {
    DockedSearchBar(
        modifier =
            Modifier.align(Alignment.TopCenter).padding(top = 8.dp).semantics {
                traversalIndex = 0f
            },
        inputField = {
            SearchBarDefaults.InputField(
                state = textFieldState,
                onSearch = { expanded = false },
                expanded = expanded,
                onExpandedChange = { expanded = it },
                placeholder = { Text("Hinted search text") },
                leadingIcon = { Icon(Icons.Default.Search, contentDescription = null) },
                trailingIcon = { Icon(Icons.Default.MoreVert, contentDescription = null) },
            )
        },
        expanded = expanded,
        onExpandedChange = { expanded = it },
    ) {
        Column(Modifier.verticalScroll(rememberScrollState())) {
            repeat(4) { idx ->
                val resultText = "Suggestion $idx"
                ListItem(
                    headlineContent = { Text(resultText) },
                    supportingContent = { Text("Additional info") },
                    leadingContent = { Icon(Icons.Filled.Star, contentDescription = null) },
                    colors = ListItemDefaults.colors(containerColor = Color.Transparent),
                    modifier =
                        Modifier.clickable {
                                textFieldState.setTextAndPlaceCursorAtEnd(resultText)
                                expanded = false
                            }
                            .fillMaxWidth()
                            .padding(horizontal = 16.dp, vertical = 4.dp)
                )
            }
        }
    }

    LazyColumn(
        contentPadding = PaddingValues(start = 16.dp, top = 72.dp, end = 16.dp, bottom = 16.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp),
        modifier = Modifier.semantics { traversalIndex = 1f },
    ) {
        val list = List(100) { "Text $it" }
        items(count = list.size) {
            Text(
                text = list[it],
                modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
            )
        }
    }
}
Parameters
inputField: @Composable () -> Unit

the input field of this search bar that allows entering a query, typically a SearchBarDefaults.InputField.

expanded: Boolean

whether this search bar is expanded and showing search results.

onExpandedChange: (Boolean) -> Unit

the callback to be invoked when this search bar's expanded state is changed.

modifier: Modifier = Modifier

the Modifier to be applied to this search bar.

shape: Shape = SearchBarDefaults.dockedShape

the shape of this search bar.

colors: SearchBarColors = SearchBarDefaults.colors()

SearchBarColors that will be used to resolve the colors used for this search bar in different states. See SearchBarDefaults.colors.

tonalElevation: Dp = SearchBarDefaults.TonalElevation

when SearchBarColors.containerColor is ColorScheme.surface, a translucent primary color overlay is applied on top of the container. A higher tonal elevation value will result in a darker color in light theme and lighter color in dark theme. See also: Surface.

shadowElevation: Dp = SearchBarDefaults.ShadowElevation

the elevation for the shadow below the search bar.

content: @Composable ColumnScope.() -> Unit

the content of this search bar to display search results below the inputField.

DockedSearchBar

@ExperimentalMaterial3Api
@Composable
fun DockedSearchBar(
    query: String,
    onQueryChange: (String) -> Unit,
    onSearch: (String) -> Unit,
    active: Boolean,
    onActiveChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    placeholder: (@Composable () -> Unit)? = null,
    leadingIcon: (@Composable () -> Unit)? = null,
    trailingIcon: (@Composable () -> Unit)? = null,
    shape: Shape = SearchBarDefaults.dockedShape,
    colors: SearchBarColors = SearchBarDefaults.colors(),
    tonalElevation: Dp = SearchBarDefaults.TonalElevation,
    shadowElevation: Dp = SearchBarDefaults.ShadowElevation,
    interactionSource: MutableInteractionSource? = null,
    content: @Composable ColumnScope.() -> Unit
): Unit
@Composable
fun DropdownMenu(
    expanded: Boolean,
    onDismissRequest: () -> Unit,
    modifier: Modifier = Modifier,
    offset: DpOffset = DpOffset(0.dp, 0.dp),
    scrollState: ScrollState = rememberScrollState(),
    properties: PopupProperties = DefaultMenuProperties,
    shape: Shape = MenuDefaults.shape,
    containerColor: Color = MenuDefaults.containerColor,
    tonalElevation: Dp = MenuDefaults.TonalElevation,
    shadowElevation: Dp = MenuDefaults.ShadowElevation,
    border: BorderStroke? = null,
    content: @Composable ColumnScope.() -> Unit
): Unit

Material Design dropdown menu.

Menus display a list of choices on a temporary surface. They appear when users interact with a button, action, or other control.

Dropdown menu image

A DropdownMenu behaves similarly to a Popup, and will use the position of the parent layout to position itself on screen. Commonly a DropdownMenu will be placed in a Box with a sibling that will be used as the 'anchor'. Note that a DropdownMenu by itself will not take up any space in a layout, as the menu is displayed in a separate window, on top of other content.

The content of a DropdownMenu will typically be DropdownMenuItems, as well as custom content. Using DropdownMenuItems will result in a menu that matches the Material specification for menus. Also note that the content is placed inside a scrollable Column, so using a LazyColumn as the root layout inside content is unsupported.

onDismissRequest will be called when the menu should close - for example when there is a tap outside the menu, or when the back key is pressed.

DropdownMenu changes its positioning depending on the available space, always trying to be fully visible. Depending on layout direction, first it will try to align its start to the start of its parent, then its end to the end of its parent, and then to the edge of the window. Vertically, it will try to align its top to the bottom of its parent, then its bottom to top of its parent, and then to the edge of the window.

An offset can be provided to adjust the positioning of the menu for cases when the layout bounds of its parent do not coincide with its visual bounds.

Example usage:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material.icons.outlined.Email
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign

var expanded by remember { mutableStateOf(false) }

Box(modifier = Modifier.fillMaxSize().wrapContentSize(Alignment.TopStart)) {
    IconButton(onClick = { expanded = true }) {
        Icon(Icons.Default.MoreVert, contentDescription = "Localized description")
    }
    DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
        DropdownMenuItem(
            text = { Text("Edit") },
            onClick = { /* Handle edit! */ },
            leadingIcon = { Icon(Icons.Outlined.Edit, contentDescription = null) }
        )
        DropdownMenuItem(
            text = { Text("Settings") },
            onClick = { /* Handle settings! */ },
            leadingIcon = { Icon(Icons.Outlined.Settings, contentDescription = null) }
        )
        HorizontalDivider()
        DropdownMenuItem(
            text = { Text("Send Feedback") },
            onClick = { /* Handle send feedback! */ },
            leadingIcon = { Icon(Icons.Outlined.Email, contentDescription = null) },
            trailingIcon = { Text("F11", textAlign = TextAlign.Center) }
        )
    }
}

Example usage with a ScrollState to control the menu items scroll position:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.rememberScrollState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

var expanded by remember { mutableStateOf(false) }
val scrollState = rememberScrollState()
Box(modifier = Modifier.fillMaxSize().wrapContentSize(Alignment.TopStart)) {
    IconButton(onClick = { expanded = true }) {
        Icon(Icons.Default.MoreVert, contentDescription = "Localized description")
    }
    DropdownMenu(
        expanded = expanded,
        onDismissRequest = { expanded = false },
        scrollState = scrollState
    ) {
        repeat(30) {
            DropdownMenuItem(
                text = { Text("Item ${it + 1}") },
                onClick = { /* TODO */ },
                leadingIcon = { Icon(Icons.Outlined.Edit, contentDescription = null) }
            )
        }
    }
    LaunchedEffect(expanded) {
        if (expanded) {
            // Scroll to show the bottom menu items.
            scrollState.scrollTo(scrollState.maxValue)
        }
    }
}
Parameters
expanded: Boolean

whether the menu is expanded or not

onDismissRequest: () -> Unit

called when the user requests to dismiss the menu, such as by tapping outside the menu's bounds

modifier: Modifier = Modifier

Modifier to be applied to the menu's content

offset: DpOffset = DpOffset(0.dp, 0.dp)

DpOffset from the original position of the menu. The offset respects the LayoutDirection, so the offset's x position will be added in LTR and subtracted in RTL.

scrollState: ScrollState = rememberScrollState()

a ScrollState to used by the menu's content for items vertical scrolling

properties: PopupProperties = DefaultMenuProperties

PopupProperties for further customization of this popup's behavior

shape: Shape = MenuDefaults.shape

the shape of the menu

containerColor: Color = MenuDefaults.containerColor

the container color of the menu

tonalElevation: Dp = MenuDefaults.TonalElevation

when containerColor is ColorScheme.surface, a translucent primary color overlay is applied on top of the container. A higher tonal elevation value will result in a darker color in light theme and lighter color in dark theme. See also: Surface.

shadowElevation: Dp = MenuDefaults.ShadowElevation

the elevation for the shadow below the menu

border: BorderStroke? = null

the border to draw around the container of the menu. Pass null for no border.

content: @Composable ColumnScope.() -> Unit

the content of this dropdown menu, typically a DropdownMenuItem

@Composable
fun DropdownMenuItem(
    text: @Composable () -> Unit,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    leadingIcon: (@Composable () -> Unit)? = null,
    trailingIcon: (@Composable () -> Unit)? = null,
    enabled: Boolean = true,
    colors: MenuItemColors = MenuDefaults.itemColors(),
    contentPadding: PaddingValues = MenuDefaults.DropdownMenuItemContentPadding,
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design dropdown menu item.

Menus display a list of choices on a temporary surface. They appear when users interact with a button, action, or other control.

Dropdown menu image

Example usage:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material.icons.outlined.Email
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign

var expanded by remember { mutableStateOf(false) }

Box(modifier = Modifier.fillMaxSize().wrapContentSize(Alignment.TopStart)) {
    IconButton(onClick = { expanded = true }) {
        Icon(Icons.Default.MoreVert, contentDescription = "Localized description")
    }
    DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
        DropdownMenuItem(
            text = { Text("Edit") },
            onClick = { /* Handle edit! */ },
            leadingIcon = { Icon(Icons.Outlined.Edit, contentDescription = null) }
        )
        DropdownMenuItem(
            text = { Text("Settings") },
            onClick = { /* Handle settings! */ },
            leadingIcon = { Icon(Icons.Outlined.Settings, contentDescription = null) }
        )
        HorizontalDivider()
        DropdownMenuItem(
            text = { Text("Send Feedback") },
            onClick = { /* Handle send feedback! */ },
            leadingIcon = { Icon(Icons.Outlined.Email, contentDescription = null) },
            trailingIcon = { Text("F11", textAlign = TextAlign.Center) }
        )
    }
}
Parameters
text: @Composable () -> Unit

text of the menu item

onClick: () -> Unit

called when this menu item is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this menu item

leadingIcon: (@Composable () -> Unit)? = null

optional leading icon to be displayed at the beginning of the item's text

trailingIcon: (@Composable () -> Unit)? = null

optional trailing icon to be displayed at the end of the item's text. This trailing icon slot can also accept Text to indicate a keyboard shortcut.

enabled: Boolean = true

controls the enabled state of this menu item. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

colors: MenuItemColors = MenuDefaults.itemColors()

MenuItemColors that will be used to resolve the colors used for this menu item in different states. See MenuDefaults.itemColors.

contentPadding: PaddingValues = MenuDefaults.DropdownMenuItemContentPadding

the padding applied to the content of this menu item

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this menu item. You can use this to change the menu item's appearance or preview the menu item in different states. Note that if null is provided, interactions will still happen internally.

ElevatedAssistChip

@Composable
fun ElevatedAssistChip(
    onClick: () -> Unit,
    label: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    leadingIcon: (@Composable () -> Unit)? = null,
    trailingIcon: (@Composable () -> Unit)? = null,
    shape: Shape = AssistChipDefaults.shape,
    colors: ChipColors = AssistChipDefaults.elevatedAssistChipColors(),
    elevation: ChipElevation? = AssistChipDefaults.elevatedAssistChipElevation(),
    border: BorderStroke? = null,
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design elevated assist chip.

Chips help people enter information, make selections, filter content, or trigger actions. Chips can show multiple interactive elements together in the same area, such as a list of selectable movie times, or a series of email contacts.

Assist chips represent smart or automated actions that can span multiple apps, such as opening a calendar event from the home screen. Assist chips function as though the user asked an assistant to complete the action. They should appear dynamically and contextually in a UI.

Assist chip image

This assist chip is applied with an elevated style. If you want a flat style, use the AssistChip.

Example of an elevated AssistChip with a trailing icon:

import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.AssistChip
import androidx.compose.material3.AssistChipDefaults
import androidx.compose.material3.ElevatedAssistChip
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier

ElevatedAssistChip(
    onClick = { /* Do something! */ },
    label = { Text("Assist Chip") },
    leadingIcon = {
        Icon(
            Icons.Filled.Settings,
            contentDescription = "Localized description",
            Modifier.size(AssistChipDefaults.IconSize)
        )
    }
)
Parameters
onClick: () -> Unit

called when this chip is clicked

label: @Composable () -> Unit

text label for this chip

modifier: Modifier = Modifier

the Modifier to be applied to this chip

enabled: Boolean = true

controls the enabled state of this chip. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

leadingIcon: (@Composable () -> Unit)? = null

optional icon at the start of the chip, preceding the label text

trailingIcon: (@Composable () -> Unit)? = null

optional icon at the end of the chip

shape: Shape = AssistChipDefaults.shape

defines the shape of this chip's container, border (when border is not null), and shadow (when using elevation)

colors: ChipColors = AssistChipDefaults.elevatedAssistChipColors()

ChipColors that will be used to resolve the colors used for this chip in different states. See AssistChipDefaults.elevatedAssistChipColors.

elevation: ChipElevation? = AssistChipDefaults.elevatedAssistChipElevation()

ChipElevation used to resolve the elevation for this chip in different states. This controls the size of the shadow below the chip. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See AssistChipDefaults.elevatedAssistChipElevation.

border: BorderStroke? = null

the border to draw around the container of this chip

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this chip. You can use this to change the chip's appearance or preview the chip in different states. Note that if null is provided, interactions will still happen internally.

ElevatedButton

@Composable
fun ElevatedButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shape: Shape = ButtonDefaults.elevatedShape,
    colors: ButtonColors = ButtonDefaults.elevatedButtonColors(),
    elevation: ButtonElevation? = ButtonDefaults.elevatedButtonElevation(),
    border: BorderStroke? = null,
    contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
    interactionSource: MutableInteractionSource? = null,
    content: @Composable RowScope.() -> Unit
): Unit

Material Design elevated button.

Buttons help people initiate actions, from sending an email, to sharing a document, to liking a post.

Elevated button image

Elevated buttons are high-emphasis buttons that are essentially FilledTonalButtons with a shadow. To prevent shadow creep, only use them when absolutely necessary, such as when the button requires visual separation from patterned container.

import androidx.compose.material3.Button
import androidx.compose.material3.ElevatedButton
import androidx.compose.material3.Text

ElevatedButton(onClick = { /* Do something! */ }) { Text("Elevated Button") }

Choose the best button for an action based on the amount of emphasis it needs. The more important an action is, the higher emphasis its button should be.

The default text style for internal Text components will be set to Typography.labelLarge.

Parameters
onClick: () -> Unit

called when this button is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this button

enabled: Boolean = true

controls the enabled state of this button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

shape: Shape = ButtonDefaults.elevatedShape

defines the shape of this button's container, border (when border is not null), and shadow (when using elevation)

colors: ButtonColors = ButtonDefaults.elevatedButtonColors()

ButtonColors that will be used to resolve the colors for this button in different states. See ButtonDefaults.elevatedButtonColors.

elevation: ButtonElevation? = ButtonDefaults.elevatedButtonElevation()

ButtonElevation used to resolve the elevation for this button in different states. This controls the size of the shadow below the button. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See ButtonDefaults.elevatedButtonElevation.

border: BorderStroke? = null

the border to draw around the container of this button

contentPadding: PaddingValues = ButtonDefaults.ContentPadding

the spacing values to apply internally between the container and the content

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this button. You can use this to change the button's appearance or preview the button in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable RowScope.() -> Unit

The content displayed on the button, expected to be text, icon or image.

ElevatedCard

@Composable
fun ElevatedCard(
    modifier: Modifier = Modifier,
    shape: Shape = CardDefaults.elevatedShape,
    colors: CardColors = CardDefaults.elevatedCardColors(),
    elevation: CardElevation = CardDefaults.elevatedCardElevation(),
    content: @Composable ColumnScope.() -> Unit
): Unit

Material Design elevated card.

Elevated cards contain content and actions that relate information about a subject. They have a drop shadow, providing more separation from the background than filled cards, but less than outlined cards.

This ElevatedCard does not handle input events - see the other ElevatedCard overloads if you want a clickable or selectable ElevatedCard.

Elevated card image

Elevated card sample:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Card
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Text
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

ElevatedCard(Modifier.size(width = 180.dp, height = 100.dp)) {
    Box(Modifier.fillMaxSize()) { Text("Card content", Modifier.align(Alignment.Center)) }
}
Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this card

shape: Shape = CardDefaults.elevatedShape

defines the shape of this card's container and shadow (when using elevation)

colors: CardColors = CardDefaults.elevatedCardColors()

CardColors that will be used to resolve the color(s) used for this card in different states. See CardDefaults.elevatedCardElevation.

elevation: CardElevation = CardDefaults.elevatedCardElevation()

CardElevation used to resolve the elevation for this card in different states. This controls the size of the shadow below the card. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See also: Surface.

content: @Composable ColumnScope.() -> Unit

The content displayed on the card

ElevatedCard

@Composable
fun ElevatedCard(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shape: Shape = CardDefaults.elevatedShape,
    colors: CardColors = CardDefaults.elevatedCardColors(),
    elevation: CardElevation = CardDefaults.elevatedCardElevation(),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable ColumnScope.() -> Unit
): Unit

Material Design elevated card.

Elevated cards contain content and actions that relate information about a subject. They have a drop shadow, providing more separation from the background than filled cards, but less than outlined cards.

This ElevatedCard handles click events, calling its onClick lambda.

Elevated card image

Clickable elevated card sample:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Card
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Text
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

ElevatedCard(
    onClick = { /* Do something */ },
    modifier = Modifier.size(width = 180.dp, height = 100.dp)
) {
    Box(Modifier.fillMaxSize()) { Text("Clickable", Modifier.align(Alignment.Center)) }
}
Parameters
onClick: () -> Unit

called when this card is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this card

enabled: Boolean = true

controls the enabled state of this card. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

shape: Shape = CardDefaults.elevatedShape

defines the shape of this card's container and shadow (when using elevation)

colors: CardColors = CardDefaults.elevatedCardColors()

CardColors that will be used to resolve the color(s) used for this card in different states. See CardDefaults.elevatedCardElevation.

elevation: CardElevation = CardDefaults.elevatedCardElevation()

CardElevation used to resolve the elevation for this card in different states. This controls the size of the shadow below the card. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See also: Surface.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this card. You can use this to change the card's appearance or preview the card in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable ColumnScope.() -> Unit

The content displayed on the card

ElevatedFilterChip

@Composable
fun ElevatedFilterChip(
    selected: Boolean,
    onClick: () -> Unit,
    label: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    leadingIcon: (@Composable () -> Unit)? = null,
    trailingIcon: (@Composable () -> Unit)? = null,
    shape: Shape = FilterChipDefaults.shape,
    colors: SelectableChipColors = FilterChipDefaults.elevatedFilterChipColors(),
    elevation: SelectableChipElevation? = FilterChipDefaults.elevatedFilterChipElevation(),
    border: BorderStroke? = null,
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design elevated filter chip.

Chips help people enter information, make selections, filter content, or trigger actions. Chips can show multiple interactive elements together in the same area, such as a list of selectable movie times, or a series of email contacts.

Filter chips use tags or descriptive words to filter content. They can be a good alternative to toggle buttons or checkboxes.

Filter chip image

This filter chip is applied with an elevated style. If you want a flat style, use the FilterChip.

Tapping on a filter chip toggles its selection state. A selection state leadingIcon can be provided (e.g. a checkmark) to be appended at the starting edge of the chip's label.

Example of an elevated FilterChip with a trailing icon:

import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Done
import androidx.compose.material3.ElevatedFilterChip
import androidx.compose.material3.FilterChip
import androidx.compose.material3.FilterChipDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier

var selected by remember { mutableStateOf(false) }
ElevatedFilterChip(
    selected = selected,
    onClick = { selected = !selected },
    label = { Text("Filter chip") },
    leadingIcon =
        if (selected) {
            {
                Icon(
                    imageVector = Icons.Filled.Done,
                    contentDescription = "Localized Description",
                    modifier = Modifier.size(FilterChipDefaults.IconSize)
                )
            }
        } else {
            null
        }
)
Parameters
selected: Boolean

whether this chip is selected or not

onClick: () -> Unit

called when this chip is clicked

label: @Composable () -> Unit

text label for this chip

modifier: Modifier = Modifier

the Modifier to be applied to this chip

enabled: Boolean = true

controls the enabled state of this chip. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

leadingIcon: (@Composable () -> Unit)? = null

optional icon at the start of the chip, preceding the label text. When selected is true, this icon may visually indicate that the chip is selected (for example, via a checkmark icon).

trailingIcon: (@Composable () -> Unit)? = null

optional icon at the end of the chip

shape: Shape = FilterChipDefaults.shape

defines the shape of this chip's container, border (when border is not null), and shadow (when using elevation)

colors: SelectableChipColors = FilterChipDefaults.elevatedFilterChipColors()

SelectableChipColors that will be used to resolve the colors used for this chip in different states. See FilterChipDefaults.elevatedFilterChipColors.

elevation: SelectableChipElevation? = FilterChipDefaults.elevatedFilterChipElevation()

SelectableChipElevation used to resolve the elevation for this chip in different states. This controls the size of the shadow below the chip. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See FilterChipDefaults.filterChipElevation.

border: BorderStroke? = null

the border to draw around the container of this chip. Pass null for no border. See FilterChipDefaults.filterChipBorder.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this chip. You can use this to change the chip's appearance or preview the chip in different states. Note that if null is provided, interactions will still happen internally.

ElevatedSuggestionChip

@Composable
fun ElevatedSuggestionChip(
    onClick: () -> Unit,
    label: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    icon: (@Composable () -> Unit)? = null,
    shape: Shape = SuggestionChipDefaults.shape,
    colors: ChipColors = SuggestionChipDefaults.elevatedSuggestionChipColors(),
    elevation: ChipElevation? = SuggestionChipDefaults.elevatedSuggestionChipElevation(),
    border: BorderStroke? = null,
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design elevated suggestion chip.

Chips help people enter information, make selections, filter content, or trigger actions. Chips can show multiple interactive elements together in the same area, such as a list of selectable movie times, or a series of email contacts.

Suggestion chips help narrow a user's intent by presenting dynamically generated suggestions, such as possible responses or search filters.

Suggestion chip image

This suggestion chip is applied with an elevated style. If you want a flat style, use the SuggestionChip.

Example of an elevated SuggestionChip with a trailing icon:

import androidx.compose.material3.ElevatedSuggestionChip
import androidx.compose.material3.SuggestionChip
import androidx.compose.material3.Text

ElevatedSuggestionChip(onClick = { /* Do something! */ }, label = { Text("Suggestion Chip") })
Parameters
onClick: () -> Unit

called when this chip is clicked

label: @Composable () -> Unit

text label for this chip

modifier: Modifier = Modifier

the Modifier to be applied to this chip

enabled: Boolean = true

controls the enabled state of this chip. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

icon: (@Composable () -> Unit)? = null

optional icon at the start of the chip, preceding the label text

shape: Shape = SuggestionChipDefaults.shape

defines the shape of this chip's container, border (when border is not null), and shadow (when using elevation)

colors: ChipColors = SuggestionChipDefaults.elevatedSuggestionChipColors()

ChipColors that will be used to resolve the colors used for this chip in

elevation: ChipElevation? = SuggestionChipDefaults.elevatedSuggestionChipElevation()

ChipElevation used to resolve the elevation for this chip in different states. This controls the size of the shadow below the chip. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See Surface and SuggestionChipDefaults.elevatedSuggestionChipElevation.

border: BorderStroke? = null

the border to draw around the container of this chip different states. See SuggestionChipDefaults.elevatedSuggestionChipColors.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this chip. You can use this to change the chip's appearance or preview the chip in different states. Note that if null is provided, interactions will still happen internally.

ElevatedToggleButton

@Composable
@ExperimentalMaterial3ExpressiveApi
fun ElevatedToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shapes: ButtonShapes = ToggleButtonDefaults.shapes(),
    colors: ToggleButtonColors = ToggleButtonDefaults.elevatedToggleButtonColors(),
    elevation: ButtonElevation? = ButtonDefaults.elevatedButtonElevation(),
    border: BorderStroke? = null,
    contentPadding: PaddingValues = ToggleButtonDefaults.ContentPadding,
    interactionSource: MutableInteractionSource? = null,
    content: @Composable RowScope.() -> Unit
): Unit

TODO link to mio page when available.

Toggle button is a toggleable button that switches between primary and tonal colors depending on checked's value. It also morphs between the three shapes provided in shapes depending on the state of the interaction with the toggle button as long as the three shapes provided our CornerBasedShapes. If a shape in shapes isn't a CornerBasedShape, then toggle button will toggle between the ButtonShapes according to user interaction.

TODO link to an image when available

Elevated toggle buttons are high-emphasis Toggle buttons. To prevent shadow creep, only use them when absolutely necessary, such as when the toggle button requires visual separation from patterned container.

see ElevatedButton for a static button that doesn't need to be toggled.

import androidx.compose.material3.ElevatedToggleButton
import androidx.compose.material3.Text
import androidx.compose.material3.ToggleButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var checked by remember { mutableStateOf(false) }
ElevatedToggleButton(checked = checked, onCheckedChange = { checked = it }) {
    Text("Elevated Button")
}
Parameters
checked: Boolean

whether the toggle button is toggled on or off.

onCheckedChange: (Boolean) -> Unit

called when the toggle button is clicked.

modifier: Modifier = Modifier

the Modifier to be applied to the toggle button.

enabled: Boolean = true

controls the enabled state of this toggle button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

shapes: ButtonShapes = ToggleButtonDefaults.shapes()

the ButtonShapes that the toggle button will morph between depending on the user's interaction with the toggle button.

colors: ToggleButtonColors = ToggleButtonDefaults.elevatedToggleButtonColors()

ToggleButtonColors that will be used to resolve the colors used for this toggle button in different states. See ToggleButtonDefaults.elevatedToggleButtonColors.

elevation: ButtonElevation? = ButtonDefaults.elevatedButtonElevation()

ButtonElevation used to resolve the elevation for this button in different states. This controls the size of the shadow below the button. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay.

border: BorderStroke? = null

the border to draw around the container of this toggle button.

contentPadding: PaddingValues = ToggleButtonDefaults.ContentPadding

the spacing values to apply internally between the container and the content

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this toggle button. You can use this to change the toggle button's appearance or preview the toggle button in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable RowScope.() -> Unit

The content displayed on the toggle button, expected to be text, icon or image.

ExposedDropdownMenuBox

@ExperimentalMaterial3Api
@Composable
fun ExposedDropdownMenuBox(
    expanded: Boolean,
    onExpandedChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    content: @Composable ExposedDropdownMenuBoxScope.() -> Unit
): Unit

Material Design Exposed Dropdown Menu.

Menus display a list of choices on a temporary surface. They appear when users interact with a button, action, or other control.

Exposed dropdown menus, sometimes also called "spinners" or "combo boxes", display the currently selected item in a text field to which the menu is anchored. In some cases, it can accept and display user input (whether or not it’s listed as a menu choice), in which case it may be used to implement autocomplete.

Exposed dropdown menu image

The ExposedDropdownMenuBox is expected to contain a TextField (or OutlinedTextField) and ExposedDropdownMenu as content. The menuAnchor modifier should be passed to the text field.

An example of a read-only Exposed Dropdown Menu:

import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.TextFieldState
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExposedDropdownMenuAnchorType
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier

val options: List<String> = SampleData.take(5)
var expanded by remember { mutableStateOf(false) }
val textFieldState = rememberTextFieldState(options[0])

ExposedDropdownMenuBox(
    expanded = expanded,
    onExpandedChange = { expanded = it },
) {
    TextField(
        // The `menuAnchor` modifier must be passed to the text field to handle
        // expanding/collapsing the menu on click. A read-only text field has
        // the anchor type `PrimaryNotEditable`.
        modifier = Modifier.menuAnchor(ExposedDropdownMenuAnchorType.PrimaryNotEditable),
        state = textFieldState,
        readOnly = true,
        lineLimits = TextFieldLineLimits.SingleLine,
        label = { Text("Label") },
        trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
        colors = ExposedDropdownMenuDefaults.textFieldColors(),
    )
    ExposedDropdownMenu(
        expanded = expanded,
        onDismissRequest = { expanded = false },
    ) {
        options.forEach { option ->
            DropdownMenuItem(
                text = { Text(option, style = MaterialTheme.typography.bodyLarge) },
                onClick = {
                    textFieldState.setTextAndPlaceCursorAtEnd(option)
                    expanded = false
                },
                contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
            )
        }
    }
}

An example of an editable Exposed Dropdown Menu:

import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.TextFieldState
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExposedDropdownMenuAnchorType
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val options: List<String> = SampleData
val textFieldState = rememberTextFieldState()

// The text that the user inputs into the text field can be used to filter the options.
// This sample uses string subsequence matching.
val filteredOptions = options.filteredBy(textFieldState.text)

val (allowExpanded, setExpanded) = remember { mutableStateOf(false) }
val expanded = allowExpanded && filteredOptions.isNotEmpty()

ExposedDropdownMenuBox(
    expanded = expanded,
    onExpandedChange = setExpanded,
) {
    TextField(
        // The `menuAnchor` modifier must be passed to the text field to handle
        // expanding/collapsing the menu on click. An editable text field has
        // the anchor type `PrimaryEditable`.
        modifier =
            Modifier.width(280.dp).menuAnchor(ExposedDropdownMenuAnchorType.PrimaryEditable),
        state = textFieldState,
        lineLimits = TextFieldLineLimits.SingleLine,
        label = { Text("Label") },
        trailingIcon = {
            ExposedDropdownMenuDefaults.TrailingIcon(
                expanded = expanded,
                // If the text field is editable, it is recommended to make the
                // trailing icon a `menuAnchor` of type `SecondaryEditable`. This
                // provides a better experience for certain accessibility services
                // to choose a menu option without typing.
                modifier = Modifier.menuAnchor(ExposedDropdownMenuAnchorType.SecondaryEditable),
            )
        },
        colors = ExposedDropdownMenuDefaults.textFieldColors(),
    )
    ExposedDropdownMenu(
        modifier = Modifier.heightIn(max = 280.dp),
        expanded = expanded,
        onDismissRequest = { setExpanded(false) },
    ) {
        filteredOptions.forEach { option ->
            DropdownMenuItem(
                text = { Text(option, style = MaterialTheme.typography.bodyLarge) },
                onClick = {
                    textFieldState.setTextAndPlaceCursorAtEnd(option.text)
                    setExpanded(false)
                },
                contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
            )
        }
    }
}

An example of an editable Exposed Dropdown Menu used like a MultiAutoCompleteTextView:

import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.TextFieldState
import androidx.compose.foundation.text.input.insert
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExposedDropdownMenuAnchorType
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.substring
import androidx.compose.ui.unit.dp

/**
 * Returns the TextRange of the current token around the cursor, where commas define token
 * boundaries.
 */
fun TextFieldState.currentTokenRange(): TextRange? {
    if (!selection.collapsed) return null

    val cursor = selection.start
    var start = cursor
    while (start > 0 && text[start - 1] != ',') {
        start--
    }
    while (start < cursor && text[start] == ' ') {
        start++
    }

    var end = cursor
    while (end < text.length && text[end] != ',') {
        end++
    }
    return TextRange(start, end)
}

fun TextFieldState.replaceThenAddComma(start: Int, end: Int, text: CharSequence) = edit {
    replace(start, end, text)
    val afterText = start + text.length
    if (afterText == this.length || this.charAt(afterText) != ',') {
        insert(afterText, ", ")
        placeCursorBeforeCharAt(afterText + 2)
    } else {
        placeCursorAfterCharAt(afterText)
    }
}

val allOptions: List<String> = SampleData
val textFieldState = rememberTextFieldState()
val tokenSelection = textFieldState.currentTokenRange()
val tokenAtCursor =
    if (tokenSelection != null) textFieldState.text.substring(tokenSelection) else ""
val filteredOptions =
    if (tokenAtCursor.isBlank()) emptyList() else allOptions.filteredBy(tokenAtCursor)

val (allowExpanded, setExpanded) = remember { mutableStateOf(false) }
val expanded = allowExpanded && filteredOptions.isNotEmpty()

ExposedDropdownMenuBox(
    expanded = expanded,
    onExpandedChange = setExpanded,
) {
    TextField(
        modifier =
            Modifier.width(280.dp).menuAnchor(ExposedDropdownMenuAnchorType.PrimaryEditable),
        state = textFieldState,
        lineLimits = TextFieldLineLimits.SingleLine,
        label = { Text("Label") },
        trailingIcon = {
            ExposedDropdownMenuDefaults.TrailingIcon(
                expanded = expanded,
                modifier = Modifier.menuAnchor(ExposedDropdownMenuAnchorType.SecondaryEditable),
            )
        },
        colors = ExposedDropdownMenuDefaults.textFieldColors(),
    )
    ExposedDropdownMenu(
        modifier = Modifier.heightIn(max = 280.dp),
        expanded = expanded,
        onDismissRequest = { setExpanded(false) },
    ) {
        filteredOptions.forEach { option ->
            DropdownMenuItem(
                text = { Text(option, style = MaterialTheme.typography.bodyLarge) },
                onClick = {
                    if (tokenSelection != null) {
                        textFieldState.replaceThenAddComma(
                            tokenSelection.start,
                            tokenSelection.end,
                            option
                        )
                    }
                },
                contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
            )
        }
    }
}
Parameters
expanded: Boolean

whether the menu is expanded or not

onExpandedChange: (Boolean) -> Unit

called when the exposed dropdown menu is clicked and the expansion state changes.

modifier: Modifier = Modifier

the Modifier to be applied to this ExposedDropdownMenuBox

content: @Composable ExposedDropdownMenuBoxScope.() -> Unit

the content of this ExposedDropdownMenuBox, typically a TextField and an ExposedDropdownMenu.

ExtendedFloatingActionButton

@Composable
fun ExtendedFloatingActionButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    shape: Shape = FloatingActionButtonDefaults.extendedFabShape,
    containerColor: Color = FloatingActionButtonDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable RowScope.() -> Unit
): Unit

Material Design extended floating action button.

Extended FABs help people take primary actions. They're wider than FABs to accommodate a text label and larger target area.

Extended FAB image

The other extended floating action button overload supports a text label and icon.

import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Text

ExtendedFloatingActionButton(onClick = { /* do something */ }) { Text(text = "Extended FAB") }
Parameters
onClick: () -> Unit

called when this FAB is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this FAB

shape: Shape = FloatingActionButtonDefaults.extendedFabShape

defines the shape of this FAB's container and shadow (when using elevation)

containerColor: Color = FloatingActionButtonDefaults.containerColor

the color used for the background of this FAB. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this FAB. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation()

FloatingActionButtonElevation used to resolve the elevation for this FAB in different states. This controls the size of the shadow below the FAB. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See also: Surface.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this FAB. You can use this to change the FAB's appearance or preview the FAB in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable RowScope.() -> Unit

the content of this FAB, typically a Text label

ExtendedFloatingActionButton

@Composable
fun ExtendedFloatingActionButton(
    text: @Composable () -> Unit,
    icon: @Composable () -> Unit,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    expanded: Boolean = true,
    shape: Shape = FloatingActionButtonDefaults.extendedFabShape,
    containerColor: Color = FloatingActionButtonDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design extended floating action button.

Extended FABs help people take primary actions. They're wider than FABs to accommodate a text label and larger target area.

Extended FAB image

The other extended floating action button overload is for FABs without an icon.

Default content description for accessibility is extended from the extended fabs icon. For custom behavior, you can provide your own via Modifier.semantics.

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.Text

ExtendedFloatingActionButton(
    onClick = { /* do something */ },
    icon = { Icon(Icons.Filled.Add, "Localized description") },
    text = { Text(text = "Extended FAB") },
)
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FabPosition
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val listState = rememberLazyListState()
// The FAB is initially expanded. Once the first visible item is past the first item we
// collapse the FAB. We use a remembered derived state to minimize unnecessary compositions.
val expandedFab by remember { derivedStateOf { listState.firstVisibleItemIndex == 0 } }
Scaffold(
    floatingActionButton = {
        ExtendedFloatingActionButton(
            onClick = { /* do something */ },
            expanded = expandedFab,
            icon = { Icon(Icons.Filled.Add, "Localized Description") },
            text = { Text(text = "Extended FAB") },
        )
    },
    floatingActionButtonPosition = FabPosition.End,
) {
    LazyColumn(state = listState, modifier = Modifier.fillMaxSize()) {
        for (index in 0 until 100) {
            item { Text(text = "List item - $index", modifier = Modifier.padding(24.dp)) }
        }
    }
}
Parameters
text: @Composable () -> Unit

label displayed inside this FAB

icon: @Composable () -> Unit

icon for this FAB, typically an Icon

onClick: () -> Unit

called when this FAB is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this FAB

expanded: Boolean = true

controls the expansion state of this FAB. In an expanded state, the FAB will show both the icon and text. In a collapsed state, the FAB will show only the icon.

shape: Shape = FloatingActionButtonDefaults.extendedFabShape

defines the shape of this FAB's container and shadow (when using elevation)

containerColor: Color = FloatingActionButtonDefaults.containerColor

the color used for the background of this FAB. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this FAB. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation()

FloatingActionButtonElevation used to resolve the elevation for this FAB in different states. This controls the size of the shadow below the FAB. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See also: Surface.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this FAB. You can use this to change the FAB's appearance or preview the FAB in different states. Note that if null is provided, interactions will still happen internally.

FilledIconButton

@Composable
fun FilledIconButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shape: Shape = IconButtonDefaults.filledShape,
    colors: IconButtonColors = IconButtonDefaults.filledIconButtonColors(),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable () -> Unit
): Unit

Material Design filled icon button.

Icon buttons help people take supplementary actions with a single tap. They’re used when a compact button is required, such as in a toolbar or image list.

Filled icon button image

content should typically be an Icon (see androidx.compose.material.icons.Icons). If using a custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.

Filled icon button sample:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton

FilledIconButton(onClick = { /* doSomething() */ }) {
    Icon(Icons.Filled.Lock, contentDescription = "Localized description")
}
Parameters
onClick: () -> Unit

called when this icon button is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this icon button

enabled: Boolean = true

controls the enabled state of this icon button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

shape: Shape = IconButtonDefaults.filledShape

defines the shape of this icon button's container

colors: IconButtonColors = IconButtonDefaults.filledIconButtonColors()

IconButtonColors that will be used to resolve the colors used for this icon button in different states. See IconButtonDefaults.filledIconButtonColors.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this icon button. You can use this to change the icon button's appearance or preview the icon button in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable () -> Unit

the content of this icon button, typically an Icon

FilledIconToggleButton

@Composable
fun FilledIconToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shape: Shape = IconButtonDefaults.filledShape,
    colors: IconToggleButtonColors = IconButtonDefaults.filledIconToggleButtonColors(),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable () -> Unit
): Unit

Material Design filled icon toggle button.

Icon buttons help people take supplementary actions with a single tap. They’re used when a compact button is required, such as in a toolbar or image list.

Filled icon toggle button image

content should typically be an Icon (see androidx.compose.material.icons.Icons). If using a custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.

Toggleable filled icon button sample:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material3.FilledIconToggleButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconToggleButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var checked by remember { mutableStateOf(false) }
FilledIconToggleButton(checked = checked, onCheckedChange = { checked = it }) {
    if (checked) {
        Icon(Icons.Filled.Lock, contentDescription = "Localized description")
    } else {
        Icon(Icons.Outlined.Lock, contentDescription = "Localized description")
    }
}
Parameters
checked: Boolean

whether this icon button is toggled on or off

onCheckedChange: (Boolean) -> Unit

called when this icon button is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this icon button

enabled: Boolean = true

controls the enabled state of this icon button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

shape: Shape = IconButtonDefaults.filledShape

defines the shape of this icon button's container

colors: IconToggleButtonColors = IconButtonDefaults.filledIconToggleButtonColors()

IconToggleButtonColors that will be used to resolve the colors used for this icon button in different states. See IconButtonDefaults.filledIconToggleButtonColors.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this icon button. You can use this to change the icon button's appearance or preview the icon button in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable () -> Unit

the content of this icon button, typically an Icon

FilledIconToggleButton

@ExperimentalMaterial3ExpressiveApi
@Composable
fun FilledIconToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    shapes: IconButtonShapes,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: IconToggleButtonColors = IconButtonDefaults.filledIconToggleButtonColors(),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable () -> Unit
): Unit

Material Design filled icon toggle button.

Icon buttons help people take supplementary actions with a single tap. They’re used when a compact button is required, such as in a toolbar or image list.

Filled icon toggle button image

content should typically be an Icon (see androidx.compose.material.icons.Icons). If using a custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.

Toggleable filled icon button sample:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material3.FilledIconToggleButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.IconButtonShapes
import androidx.compose.material3.IconToggleButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var checked by remember { mutableStateOf(false) }
FilledIconToggleButton(
    checked = checked,
    onCheckedChange = { checked = it },
    shapes =
        IconButtonShapes(
            shape = IconButtonDefaults.smallRoundShape,
            pressedShape = IconButtonDefaults.smallPressedShape,
            checkedShape = IconButtonDefaults.smallSquareShape,
        )
) {
    if (checked) {
        Icon(Icons.Filled.Lock, contentDescription = "Localized description")
    } else {
        Icon(Icons.Outlined.Lock, contentDescription = "Localized description")
    }
}
Parameters
checked: Boolean

whether this icon button is toggled on or off

onCheckedChange: (Boolean) -> Unit

called when this icon button is clicked

shapes: IconButtonShapes

the IconButtonShapes that the icon toggle button will morph between depending on the user's interaction with the icon toggle button.

modifier: Modifier = Modifier

the Modifier to be applied to this icon button

enabled: Boolean = true

controls the enabled state of this icon button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

colors: IconToggleButtonColors = IconButtonDefaults.filledIconToggleButtonColors()

IconToggleButtonColors that will be used to resolve the colors used for this icon button in different states. See IconButtonDefaults.filledIconToggleButtonColors.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this icon button. You can use this to change the icon button's appearance or preview the icon button in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable () -> Unit

the content of this icon button, typically an Icon

FilledTonalButton

@Composable
fun FilledTonalButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shape: Shape = ButtonDefaults.filledTonalShape,
    colors: ButtonColors = ButtonDefaults.filledTonalButtonColors(),
    elevation: ButtonElevation? = ButtonDefaults.filledTonalButtonElevation(),
    border: BorderStroke? = null,
    contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
    interactionSource: MutableInteractionSource? = null,
    content: @Composable RowScope.() -> Unit
): Unit

Material Design filled tonal button.

Buttons help people initiate actions, from sending an email, to sharing a document, to liking a post.

Filled tonal button image

Filled tonal buttons are medium-emphasis buttons that is an alternative middle ground between default Buttons (filled) and OutlinedButtons. They can be used in contexts where lower-priority button requires slightly more emphasis than an outline would give, such as "Next" in an onboarding flow. Tonal buttons use the secondary color mapping.

import androidx.compose.material3.Button
import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.Text

FilledTonalButton(onClick = { /* Do something! */ }) { Text("Filled Tonal Button") }

Choose the best button for an action based on the amount of emphasis it needs. The more important an action is, the higher emphasis its button should be.

The default text style for internal Text components will be set to Typography.labelLarge.

Parameters
onClick: () -> Unit

called when this button is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this button

enabled: Boolean = true

controls the enabled state of this button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

shape: Shape = ButtonDefaults.filledTonalShape

defines the shape of this button's container, border (when border is not null), and shadow (when using elevation)

colors: ButtonColors = ButtonDefaults.filledTonalButtonColors()

ButtonColors that will be used to resolve the colors for this button in different states. See ButtonDefaults.filledTonalButtonColors.

elevation: ButtonElevation? = ButtonDefaults.filledTonalButtonElevation()

ButtonElevation used to resolve the elevation for this button in different states. This controls the size of the shadow below the button. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay.

border: BorderStroke? = null

the border to draw around the container of this button

contentPadding: PaddingValues = ButtonDefaults.ContentPadding

the spacing values to apply internally between the container and the content

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this button. You can use this to change the button's appearance or preview the button in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable RowScope.() -> Unit

The content displayed on the button, expected to be text, icon or image.

FilledTonalIconButton

@Composable
fun FilledTonalIconButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shape: Shape = IconButtonDefaults.filledShape,
    colors: IconButtonColors = IconButtonDefaults.filledTonalIconButtonColors(),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable () -> Unit
): Unit

Material Design filled tonal icon button.

Icon buttons help people take supplementary actions with a single tap. They’re used when a compact button is required, such as in a toolbar or image list.

Filled tonal icon button image

A filled tonal icon button is a medium-emphasis icon button that is an alternative middle ground between the default FilledIconButton and OutlinedIconButton. They can be used in contexts where the lower-priority icon button requires slightly more emphasis than an outline would give.

content should typically be an Icon (see androidx.compose.material.icons.Icons). If using a custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.

Filled tonal icon button sample:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material3.FilledTonalIconButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton

FilledTonalIconButton(onClick = { /* doSomething() */ }) {
    Icon(Icons.Filled.Lock, contentDescription = "Localized description")
}
Parameters
onClick: () -> Unit

called when this icon button is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this icon button

enabled: Boolean = true

controls the enabled state of this icon button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

shape: Shape = IconButtonDefaults.filledShape

defines the shape of this icon button's container

colors: IconButtonColors = IconButtonDefaults.filledTonalIconButtonColors()

IconButtonColors that will be used to resolve the colors used for this icon button in different states. See IconButtonDefaults.filledIconButtonColors.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this icon button. You can use this to change the icon button's appearance or preview the icon button in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable () -> Unit

the content of this icon button, typically an Icon

FilledTonalIconToggleButton

@Composable
fun FilledTonalIconToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shape: Shape = IconButtonDefaults.filledShape,
    colors: IconToggleButtonColors = IconButtonDefaults.filledTonalIconToggleButtonColors(),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable () -> Unit
): Unit

Material Design filled tonal icon toggle button.

Icon buttons help people take supplementary actions with a single tap. They’re used when a compact button is required, such as in a toolbar or image list.

Filled tonal icon toggle button image

A filled tonal toggle icon button is a medium-emphasis icon button that is an alternative middle ground between the default FilledIconToggleButton and OutlinedIconToggleButton. They can be used in contexts where the lower-priority icon button requires slightly more emphasis than an outline would give.

content should typically be an Icon (see androidx.compose.material.icons.Icons). If using a custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.

Toggleable filled tonal icon button sample:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material3.FilledTonalIconToggleButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconToggleButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var checked by remember { mutableStateOf(false) }
FilledTonalIconToggleButton(checked = checked, onCheckedChange = { checked = it }) {
    if (checked) {
        Icon(Icons.Filled.Lock, contentDescription = "Localized description")
    } else {
        Icon(Icons.Outlined.Lock, contentDescription = "Localized description")
    }
}
Parameters
checked: Boolean

whether this icon button is toggled on or off

onCheckedChange: (Boolean) -> Unit

called when this icon button is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this icon button

enabled: Boolean = true

controls the enabled state of this icon button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

shape: Shape = IconButtonDefaults.filledShape

defines the shape of this icon button's container

colors: IconToggleButtonColors = IconButtonDefaults.filledTonalIconToggleButtonColors()

IconToggleButtonColors that will be used to resolve the colors used for this icon button in different states. See IconButtonDefaults.filledIconToggleButtonColors.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this icon button. You can use this to change the icon button's appearance or preview the icon button in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable () -> Unit

the content of this icon button, typically an Icon

FilledTonalIconToggleButton

@ExperimentalMaterial3ExpressiveApi
@Composable
fun FilledTonalIconToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    shapes: IconButtonShapes,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: IconToggleButtonColors = IconButtonDefaults.filledTonalIconToggleButtonColors(),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable () -> Unit
): Unit

Material Design filled tonal icon toggle button.

Icon buttons help people take supplementary actions with a single tap. They’re used when a compact button is required, such as in a toolbar or image list.

Filled tonal icon toggle button image

A filled tonal toggle icon button is a medium-emphasis icon button that is an alternative middle ground between the default FilledIconToggleButton and OutlinedIconToggleButton. They can be used in contexts where the lower-priority icon button requires slightly more emphasis than an outline would give.

content should typically be an Icon (see androidx.compose.material.icons.Icons). If using a custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.

Toggleable filled tonal icon button with animatable shape sample:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material3.FilledTonalIconToggleButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.IconButtonShapes
import androidx.compose.material3.IconToggleButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var checked by remember { mutableStateOf(false) }
FilledTonalIconToggleButton(
    checked = checked,
    onCheckedChange = { checked = it },
    shapes =
        IconButtonShapes(
            shape = IconButtonDefaults.smallRoundShape,
            pressedShape = IconButtonDefaults.smallPressedShape,
            checkedShape = IconButtonDefaults.smallSquareShape,
        )
) {
    if (checked) {
        Icon(Icons.Filled.Lock, contentDescription = "Localized description")
    } else {
        Icon(Icons.Outlined.Lock, contentDescription = "Localized description")
    }
}
Parameters
checked: Boolean

whether this icon button is toggled on or off

onCheckedChange: (Boolean) -> Unit

called when this icon button is clicked

shapes: IconButtonShapes

the IconButtonShapes that the icon toggle button will morph between depending on the user's interaction with the icon toggle button.

modifier: Modifier = Modifier

the Modifier to be applied to this icon button

enabled: Boolean = true

controls the enabled state of this icon button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

colors: IconToggleButtonColors = IconButtonDefaults.filledTonalIconToggleButtonColors()

IconToggleButtonColors that will be used to resolve the colors used for this icon button in different states. See IconButtonDefaults.filledIconToggleButtonColors.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this icon button. You can use this to change the icon button's appearance or preview the icon button in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable () -> Unit

the content of this icon button, typically an Icon

FilterChip

@Composable
fun FilterChip(
    selected: Boolean,
    onClick: () -> Unit,
    label: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    leadingIcon: (@Composable () -> Unit)? = null,
    trailingIcon: (@Composable () -> Unit)? = null,
    shape: Shape = FilterChipDefaults.shape,
    colors: SelectableChipColors = FilterChipDefaults.filterChipColors(),
    elevation: SelectableChipElevation? = FilterChipDefaults.filterChipElevation(),
    border: BorderStroke? = FilterChipDefaults.filterChipBorder(enabled, selected),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design filter chip.

Chips help people enter information, make selections, filter content, or trigger actions. Chips can show multiple interactive elements together in the same area, such as a list of selectable movie times, or a series of email contacts.

Filter chips use tags or descriptive words to filter content. They can be a good alternative to toggle buttons or checkboxes.

Filter chip image

This filter chip is applied with a flat style. If you want an elevated style, use the ElevatedFilterChip.

Tapping on a filter chip toggles its selection state. A selection state leadingIcon can be provided (e.g. a checkmark) to be appended at the starting edge of the chip's label.

Example of a flat FilterChip with a trailing icon:

import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Done
import androidx.compose.material3.FilterChip
import androidx.compose.material3.FilterChipDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier

var selected by remember { mutableStateOf(false) }
FilterChip(
    selected = selected,
    onClick = { selected = !selected },
    label = { Text("Filter chip") },
    leadingIcon =
        if (selected) {
            {
                Icon(
                    imageVector = Icons.Filled.Done,
                    contentDescription = "Localized Description",
                    modifier = Modifier.size(FilterChipDefaults.IconSize)
                )
            }
        } else {
            null
        }
)

Example of a FilterChip with both a leading icon and a selected icon:

import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Done
import androidx.compose.material.icons.filled.Home
import androidx.compose.material3.FilterChip
import androidx.compose.material3.FilterChipDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier

var selected by remember { mutableStateOf(false) }
FilterChip(
    selected = selected,
    onClick = { selected = !selected },
    label = { Text("Filter chip") },
    leadingIcon =
        if (selected) {
            {
                Icon(
                    imageVector = Icons.Filled.Done,
                    contentDescription = "Localized Description",
                    modifier = Modifier.size(FilterChipDefaults.IconSize)
                )
            }
        } else {
            {
                Icon(
                    imageVector = Icons.Filled.Home,
                    contentDescription = "Localized description",
                    modifier = Modifier.size(FilterChipDefaults.IconSize)
                )
            }
        }
)
Parameters
selected: Boolean

whether this chip is selected or not

onClick: () -> Unit

called when this chip is clicked

label: @Composable () -> Unit

text label for this chip

modifier: Modifier = Modifier

the Modifier to be applied to this chip

enabled: Boolean = true

controls the enabled state of this chip. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

leadingIcon: (@Composable () -> Unit)? = null

optional icon at the start of the chip, preceding the label text. When selected is true, this icon may visually indicate that the chip is selected (for example, via a checkmark icon).

trailingIcon: (@Composable () -> Unit)? = null

optional icon at the end of the chip

shape: Shape = FilterChipDefaults.shape

defines the shape of this chip's container, border (when border is not null), and shadow (when using elevation)

colors: SelectableChipColors = FilterChipDefaults.filterChipColors()

SelectableChipColors that will be used to resolve the colors used for this chip in different states. See FilterChipDefaults.filterChipColors.

elevation: SelectableChipElevation? = FilterChipDefaults.filterChipElevation()

SelectableChipElevation used to resolve the elevation for this chip in different states. This controls the size of the shadow below the chip. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See FilterChipDefaults.filterChipElevation.

border: BorderStroke? = FilterChipDefaults.filterChipBorder(enabled, selected)

the border to draw around the container of this chip. Pass null for no border. See FilterChipDefaults.filterChipBorder.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this chip. You can use this to change the chip's appearance or preview the chip in different states. Note that if null is provided, interactions will still happen internally.

FloatingActionButton

@Composable
fun FloatingActionButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    shape: Shape = FloatingActionButtonDefaults.shape,
    containerColor: Color = FloatingActionButtonDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable () -> Unit
): Unit

Material Design floating action button.

The FAB represents the most important action on a screen. It puts key actions within reach.

FAB image

FAB typically contains an icon, for a FAB with text and an icon, see ExtendedFloatingActionButton.

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon

FloatingActionButton(
    onClick = { /* do something */ },
) {
    Icon(Icons.Filled.Add, "Localized description")
}
Parameters
onClick: () -> Unit

called when this FAB is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this FAB

shape: Shape = FloatingActionButtonDefaults.shape

defines the shape of this FAB's container and shadow (when using elevation)

containerColor: Color = FloatingActionButtonDefaults.containerColor

the color used for the background of this FAB. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this FAB. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation()

FloatingActionButtonElevation used to resolve the elevation for this FAB in different states. This controls the size of the shadow below the FAB. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See also: Surface.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this FAB. You can use this to change the FAB's appearance or preview the FAB in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable () -> Unit

the content of this FAB, typically an Icon

FloatingActionButtonMenu

@ExperimentalMaterial3ExpressiveApi
@Composable
fun FloatingActionButtonMenu(
    expanded: Boolean,
    button: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    horizontalAlignment: Alignment.Horizontal = Alignment.End,
    content: @Composable FloatingActionButtonMenuScope.() -> Unit
): Unit

FAB Menus should be used in conjunction with a ToggleFloatingActionButton to provide additional choices to the user after clicking a FAB.

import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Label
import androidx.compose.material.icons.automirrored.filled.Message
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Archive
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Contacts
import androidx.compose.material.icons.filled.People
import androidx.compose.material.icons.filled.Snooze
import androidx.compose.material3.FloatingActionButtonMenu
import androidx.compose.material3.FloatingActionButtonMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.material3.ToggleFloatingActionButton
import androidx.compose.material3.ToggleFloatingActionButtonDefaults.animateIcon
import androidx.compose.material3.animateFloatingActionButton
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.semantics.CustomAccessibilityAction
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.customActions
import androidx.compose.ui.semantics.isTraversalGroup
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.stateDescription
import androidx.compose.ui.semantics.traversalIndex
import androidx.compose.ui.unit.dp

val listState = rememberLazyListState()
val fabVisible by remember { derivedStateOf { listState.firstVisibleItemIndex == 0 } }

Box {
    LazyColumn(state = listState, modifier = Modifier.fillMaxSize()) {
        for (index in 0 until 100) {
            item { Text(text = "List item - $index", modifier = Modifier.padding(24.dp)) }
        }
    }

    val items =
        listOf(
            Icons.AutoMirrored.Filled.Message to "Reply",
            Icons.Filled.People to "Reply all",
            Icons.Filled.Contacts to "Forward",
            Icons.Filled.Snooze to "Snooze",
            Icons.Filled.Archive to "Archive",
            Icons.AutoMirrored.Filled.Label to "Label",
        )

    var fabMenuExpanded by rememberSaveable { mutableStateOf(false) }

    BackHandler(fabMenuExpanded) { fabMenuExpanded = false }

    FloatingActionButtonMenu(
        modifier = Modifier.align(Alignment.BottomEnd),
        expanded = fabMenuExpanded,
        button = {
            ToggleFloatingActionButton(
                modifier =
                    Modifier.semantics {
                            traversalIndex = -1f
                            stateDescription = if (fabMenuExpanded) "Expanded" else "Collapsed"
                            contentDescription = "Toggle menu"
                        }
                        .animateFloatingActionButton(
                            visible = fabVisible || fabMenuExpanded,
                            alignment = Alignment.BottomEnd
                        ),
                checked = fabMenuExpanded,
                onCheckedChange = { fabMenuExpanded = !fabMenuExpanded }
            ) {
                val imageVector by remember {
                    derivedStateOf {
                        if (checkedProgress > 0.5f) Icons.Filled.Close else Icons.Filled.Add
                    }
                }
                Icon(
                    painter = rememberVectorPainter(imageVector),
                    contentDescription = null,
                    modifier = Modifier.animateIcon({ checkedProgress })
                )
            }
        }
    ) {
        items.forEachIndexed { i, item ->
            FloatingActionButtonMenuItem(
                modifier =
                    Modifier.semantics {
                        isTraversalGroup = true
                        // Add a custom a11y action to allow closing the menu when focusing
                        // the last menu item, since the close button comes before the first
                        // menu item in the traversal order.
                        if (i == items.size - 1) {
                            customActions =
                                listOf(
                                    CustomAccessibilityAction(
                                        label = "Close menu",
                                        action = {
                                            fabMenuExpanded = false
                                            true
                                        }
                                    )
                                )
                        }
                    },
                onClick = { fabMenuExpanded = false },
                icon = { Icon(item.first, contentDescription = null) },
                text = { Text(text = item.second) },
            )
        }
    }
}
Parameters
expanded: Boolean

whether the FAB Menu is expanded, which will trigger a staggered animation of the FAB Menu Items

button: @Composable () -> Unit

a composable which triggers the showing and hiding of the FAB Menu Items via the expanded state, typically a ToggleFloatingActionButton

modifier: Modifier = Modifier

the Modifier to be applied to this FAB Menu

horizontalAlignment: Alignment.Horizontal = Alignment.End

the horizontal alignment of the FAB Menu Items

content: @Composable FloatingActionButtonMenuScope.() -> Unit

the content of this FAB Menu, typically a list of FloatingActionButtonMenuItems

FloatingAppBarState

@ExperimentalMaterial3ExpressiveApi
fun FloatingAppBarState(
    initialOffsetLimit: Float,
    initialOffset: Float,
    initialContentOffset: Float
): FloatingAppBarState

Creates a FloatingAppBarState.

Parameters
initialOffsetLimit: Float

the initial value for FloatingAppBarState.offsetLimit, which represents the pixel limit that a floating app bar is allowed to collapse when the scrollable content is scrolled.

initialOffset: Float

the initial value for FloatingAppBarState.offset. The initial offset should be between zero and initialOffsetLimit.

initialContentOffset: Float

the initial value for FloatingAppBarState.contentOffset

HorizontalDivider

@Composable
fun HorizontalDivider(
    modifier: Modifier = Modifier,
    thickness: Dp = DividerDefaults.Thickness,
    color: Color = DividerDefaults.color
): Unit

Material Design divider.

A divider is a thin line that groups content in lists and layouts.

Divider image

Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this divider line.

thickness: Dp = DividerDefaults.Thickness

thickness of this divider line. Using Dp.Hairline will produce a single pixel divider regardless of screen density.

color: Color = DividerDefaults.color

color of this divider line.

HorizontalFloatingAppBar

@ExperimentalMaterial3ExpressiveApi
@Composable
fun HorizontalFloatingAppBar(
    expanded: Boolean,
    modifier: Modifier = Modifier,
    containerColor: Color = FloatingAppBarDefaults.ContainerColor,
    contentPadding: PaddingValues = FloatingAppBarDefaults.ContentPadding,
    scrollBehavior: FloatingAppBarScrollBehavior? = null,
    shape: Shape = FloatingAppBarDefaults.ContainerShape,
    leadingContent: (@Composable RowScope.() -> Unit)? = null,
    trailingContent: (@Composable RowScope.() -> Unit)? = null,
    content: @Composable RowScope.() -> Unit
): Unit
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.FloatingAppBarDefaults.ScreenOffset
import androidx.compose.material3.FloatingAppBarExitDirection.Companion.Bottom
import androidx.compose.material3.HorizontalFloatingAppBar
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment.Companion.BottomCenter
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp

val context = LocalContext.current
val isTouchExplorationEnabled = remember {
    val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
    am.isEnabled && am.isTouchExplorationEnabled
}
val listState = rememberLazyListState()
var currentItem = 0
val expanded by remember {
    derivedStateOf {
        val temp = currentItem
        currentItem = listState.firstVisibleItemIndex
        listState.firstVisibleItemIndex <= temp // true if the list is scrolled up
    }
}
Scaffold(
    content = { innerPadding ->
        Box {
            LazyColumn(
                state = listState,
                contentPadding = innerPadding,
                verticalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                val list = (0..75).map { it.toString() }
                items(count = list.size) {
                    Text(
                        text = list[it],
                        style = MaterialTheme.typography.bodyLarge,
                        modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                    )
                }
            }
            HorizontalFloatingAppBar(
                modifier = Modifier.align(BottomCenter).offset(y = -ScreenOffset),
                expanded = expanded || isTouchExplorationEnabled,
                leadingContent = { leadingContent() },
                trailingContent = { trailingContent() },
                content = {
                    FilledIconButton(
                        modifier = Modifier.width(64.dp),
                        onClick = { /* doSomething() */ }
                    ) {
                        Icon(Icons.Filled.Add, contentDescription = "Localized description")
                    }
                },
            )
        }
    }
)
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.FloatingAppBarDefaults
import androidx.compose.material3.FloatingAppBarDefaults.ScreenOffset
import androidx.compose.material3.FloatingAppBarExitDirection.Companion.Bottom
import androidx.compose.material3.HorizontalFloatingAppBar
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment.Companion.BottomCenter
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp

val context = LocalContext.current
val isTouchExplorationEnabled = remember {
    val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
    am.isEnabled && am.isTouchExplorationEnabled
}
val listState = rememberLazyListState()
val exitAlwaysScrollBehavior =
    FloatingAppBarDefaults.exitAlwaysScrollBehavior(exitDirection = Bottom)
Scaffold(
    modifier = Modifier.nestedScroll(exitAlwaysScrollBehavior),
    content = { innerPadding ->
        Box {
            LazyColumn(
                state = listState,
                contentPadding = innerPadding,
                verticalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                val list = (0..75).map { it.toString() }
                items(count = list.size) {
                    Text(
                        text = list[it],
                        style = MaterialTheme.typography.bodyLarge,
                        modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                    )
                }
            }
            HorizontalFloatingAppBar(
                modifier = Modifier.align(BottomCenter).offset(y = -ScreenOffset),
                expanded = true,
                leadingContent = { leadingContent() },
                trailingContent = { trailingContent() },
                content = {
                    FilledIconButton(
                        modifier = Modifier.width(64.dp),
                        onClick = { /* doSomething() */ }
                    ) {
                        Icon(Icons.Filled.Add, contentDescription = "Localized description")
                    }
                },
                scrollBehavior =
                    if (!isTouchExplorationEnabled) exitAlwaysScrollBehavior else null,
            )
        }
    }
)
Parameters
expanded: Boolean

whether the FloatingAppBar is in expanded mode, i.e. showing leadingContent and trailingContent.

modifier: Modifier = Modifier

the Modifier to be applied to this FloatingAppBar.

containerColor: Color = FloatingAppBarDefaults.ContainerColor

the color used for the background of this FloatingAppBar. Use Color.Transparent to have no color.

contentPadding: PaddingValues = FloatingAppBarDefaults.ContentPadding

the padding applied to the content of this FloatingAppBar.

scrollBehavior: FloatingAppBarScrollBehavior? = null

a FloatingAppBarScrollBehavior. If null, this FloatingAppBar will not automatically react to scrolling.

shape: Shape = FloatingAppBarDefaults.ContainerShape

the shape used for this FloatingAppBar.

leadingContent: (@Composable RowScope.() -> Unit)? = null

the leading content of this FloatingAppBar. The default layout here is a Row, so content inside will be placed horizontally. Only showing if expanded is true.

trailingContent: (@Composable RowScope.() -> Unit)? = null

the trailing content of this FloatingAppBar. The default layout here is a Row, so content inside will be placed horizontally. Only showing if expanded is true.

content: @Composable RowScope.() -> Unit

the main content of this FloatingAppBar. The default layout here is a Row, so content inside will be placed horizontally.

@Composable
fun Icon(
    bitmap: ImageBitmap,
    contentDescription: String?,
    modifier: Modifier = Modifier,
    tint: Color = LocalContentColor.current
): Unit

A Material Design icon component that draws bitmap using tint, with a default value of LocalContentColor. If bitmap has no intrinsic size, this component will use the recommended default size. Icon is an opinionated component designed to be used with single-color icons so that they can be tinted correctly for the component they are placed in. For multicolored icons and icons that should not be tinted, use Color.Unspecified for tint. For generic images that should not be tinted, and do not follow the recommended icon size, use the generic androidx.compose.foundation.Image instead. For a clickable icon, see IconButton.

To learn more about icons, see Material Design icons

Parameters
bitmap: ImageBitmap

ImageBitmap to draw inside this icon

contentDescription: String?

text used by accessibility services to describe what this icon represents. This should always be provided unless this icon is used for decorative purposes, and does not represent a meaningful action that a user can take. This text should be localized, such as by using androidx.compose.ui.res.stringResource or similar

modifier: Modifier = Modifier

the Modifier to be applied to this icon

tint: Color = LocalContentColor.current

tint to be applied to bitmap. If Color.Unspecified is provided, then no tint is applied.

@Composable
fun Icon(
    imageVector: ImageVector,
    contentDescription: String?,
    modifier: Modifier = Modifier,
    tint: Color = LocalContentColor.current
): Unit

A Material Design icon component that draws imageVector using tint, with a default value of LocalContentColor. If imageVector has no intrinsic size, this component will use the recommended default size. Icon is an opinionated component designed to be used with single-color icons so that they can be tinted correctly for the component they are placed in. For multicolored icons and icons that should not be tinted, use Color.Unspecified for tint. For generic images that should not be tinted, and do not follow the recommended icon size, use the generic androidx.compose.foundation.Image instead. For a clickable icon, see IconButton.

To learn more about icons, see Material Design icons

Parameters
imageVector: ImageVector

ImageVector to draw inside this icon

contentDescription: String?

text used by accessibility services to describe what this icon represents. This should always be provided unless this icon is used for decorative purposes, and does not represent a meaningful action that a user can take. This text should be localized, such as by using androidx.compose.ui.res.stringResource or similar

modifier: Modifier = Modifier

the Modifier to be applied to this icon

tint: Color = LocalContentColor.current

tint to be applied to imageVector. If Color.Unspecified is provided, then no tint is applied.

@Composable
fun Icon(
    painter: Painter,
    contentDescription: String?,
    modifier: Modifier = Modifier,
    tint: Color = LocalContentColor.current
): Unit

A Material Design icon component that draws painter using tint, with a default value of LocalContentColor. If painter has no intrinsic size, this component will use the recommended default size. Icon is an opinionated component designed to be used with single-color icons so that they can be tinted correctly for the component they are placed in. For multicolored icons and icons that should not be tinted, use Color.Unspecified for tint. For generic images that should not be tinted, and do not follow the recommended icon size, use the generic androidx.compose.foundation.Image instead. For a clickable icon, see IconButton.

To learn more about icons, see Material Design icons

Parameters
painter: Painter

Painter to draw inside this icon

contentDescription: String?

text used by accessibility services to describe what this icon represents. This should always be provided unless this icon is used for decorative purposes, and does not represent a meaningful action that a user can take. This text should be localized, such as by using androidx.compose.ui.res.stringResource or similar

modifier: Modifier = Modifier

the Modifier to be applied to this icon

tint: Color = LocalContentColor.current

tint to be applied to painter. If Color.Unspecified is provided, then no tint is applied.

@Composable
@ExperimentalMaterial3Api
fun Icon(
    painter: Painter,
    tint: ColorProducer?,
    contentDescription: String?,
    modifier: Modifier = Modifier
): Unit

A Material Design icon component that draws painter using tint. If painter has no intrinsic size, this component will use the recommended default size. Icon is an opinionated component designed to be used with single-color icons so that they can be tinted correctly for the component they are placed in. For multicolored icons and icons that should not be tinted, use null for tint. For generic images that should not be tinted, and do not follow the recommended icon size, use the generic androidx.compose.foundation.Image instead. For a clickable icon, see IconButton.

To learn more about icons, see Material Design icons

Parameters
painter: Painter

Painter to draw inside this icon

tint: ColorProducer?

tint to be applied to painter. If null, then no tint is applied.

contentDescription: String?

text used by accessibility services to describe what this icon represents. This should always be provided unless this icon is used for decorative purposes, and does not represent a meaningful action that a user can take. This text should be localized, such as by using androidx.compose.ui.res.stringResource or similar

modifier: Modifier = Modifier

the Modifier to be applied to this icon

@Composable
fun IconButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: IconButtonColors = IconButtonDefaults.iconButtonColors(),
    interactionSource: MutableInteractionSource? = null,
    shape: Shape = IconButtonDefaults.standardShape,
    content: @Composable () -> Unit
): Unit

Material Design standard icon button.

Icon buttons help people take supplementary actions with a single tap. They’re used when a compact button is required, such as in a toolbar or image list.

Standard icon button image

content should typically be an Icon (see androidx.compose.material.icons.Icons). If using a custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.

Simple Usage

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton

IconButton(onClick = { /* doSomething() */ }) {
    Icon(Icons.Filled.Lock, contentDescription = "Localized description")
}

IconButton with a color tint

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.rememberVectorPainter

IconButton(onClick = { /* doSomething() */ }) {
    Icon(
        rememberVectorPainter(image = Icons.Filled.Lock),
        contentDescription = "Localized description",
        tint = Color.Red
    )
}

Small-sized narrow round shape IconButton

import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.minimumInteractiveComponentSize
import androidx.compose.ui.Modifier

// Small narrow round icon button
FilledIconButton(
    onClick = { /* doSomething() */ },
    modifier =
        Modifier.minimumInteractiveComponentSize()
            .size(
                IconButtonDefaults.xSmallContainerSize(
                    IconButtonDefaults.IconButtonWidthOption.Narrow
                )
            ),
    shape = IconButtonDefaults.xSmallSquareShape
) {
    Icon(
        Icons.Filled.Lock,
        contentDescription = "Localized description",
        modifier = Modifier.size(IconButtonDefaults.xSmallIconSize)
    )
}

Medium / default size round-shaped icon button

import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.ui.Modifier

IconButton(
    onClick = { /* doSomething() */ },
    modifier =
        Modifier.size(
            IconButtonDefaults.mediumContainerSize(
                IconButtonDefaults.IconButtonWidthOption.Wide
            )
        ),
    shape = IconButtonDefaults.mediumRoundShape
) {
    Icon(
        Icons.Filled.Lock,
        contentDescription = "Localized description",
        modifier = Modifier.size(IconButtonDefaults.mediumIconSize)
    )
}
Parameters
onClick: () -> Unit

called when this icon button is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this icon button

enabled: Boolean = true

controls the enabled state of this icon button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

colors: IconButtonColors = IconButtonDefaults.iconButtonColors()

IconButtonColors that will be used to resolve the colors used for this icon button in different states. See IconButtonDefaults.iconButtonVibrantColors and IconButtonDefaults.iconButtonColors .

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this icon button. You can use this to change the icon button's appearance or preview the icon button in different states. Note that if null is provided, interactions will still happen internally.

shape: Shape = IconButtonDefaults.standardShape

the Shape of this icon button.

content: @Composable () -> Unit

the content of this icon button, typically an Icon

IconToggleButton

@Composable
fun IconToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: IconToggleButtonColors = IconButtonDefaults.iconToggleButtonColors(),
    interactionSource: MutableInteractionSource? = null,
    shape: Shape = IconButtonDefaults.standardShape,
    content: @Composable () -> Unit
): Unit

Material Design standard icon toggle button.

Icon buttons help people take supplementary actions with a single tap. They’re used when a compact button is required, such as in a toolbar or image list.

Standard icon toggle button image

content should typically be an Icon (see androidx.compose.material.icons.Icons). If using a custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material3.Icon
import androidx.compose.material3.IconToggleButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var checked by remember { mutableStateOf(false) }
IconToggleButton(checked = checked, onCheckedChange = { checked = it }) {
    if (checked) {
        Icon(Icons.Filled.Lock, contentDescription = "Localized description")
    } else {
        Icon(Icons.Outlined.Lock, contentDescription = "Localized description")
    }
}
Parameters
checked: Boolean

whether this icon button is toggled on or off

onCheckedChange: (Boolean) -> Unit

called when this icon button is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this icon button

enabled: Boolean = true

controls the enabled state of this icon button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

colors: IconToggleButtonColors = IconButtonDefaults.iconToggleButtonColors()

IconToggleButtonColors that will be used to resolve the colors used for this icon button in different states. See IconButtonDefaults.iconToggleButtonVibrantColors and IconButtonDefaults.iconToggleButtonColors.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this icon button. You can use this to change the icon button's appearance or preview the icon button in different states. Note that if null is provided, interactions will still happen internally.

shape: Shape = IconButtonDefaults.standardShape

the Shape of this icon button.

content: @Composable () -> Unit

the content of this icon button, typically an Icon

IconToggleButton

@ExperimentalMaterial3ExpressiveApi
@Composable
fun IconToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    shapes: IconButtonShapes,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: IconToggleButtonColors = IconButtonDefaults.iconToggleButtonVibrantColors(),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable () -> Unit
): Unit

Material Design standard icon toggle button.

Icon buttons help people take supplementary actions with a single tap. They’re used when a compact button is required, such as in a toolbar or image list.

Standard icon toggle button image

content should typically be an Icon (see androidx.compose.material.icons.Icons). If using a custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material3.Icon
import androidx.compose.material3.IconToggleButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var checked by remember { mutableStateOf(false) }
IconToggleButton(checked = checked, onCheckedChange = { checked = it }) {
    if (checked) {
        Icon(Icons.Filled.Lock, contentDescription = "Localized description")
    } else {
        Icon(Icons.Outlined.Lock, contentDescription = "Localized description")
    }
}
Parameters
checked: Boolean

whether this icon button is toggled on or off

onCheckedChange: (Boolean) -> Unit

called when this icon button is clicked

shapes: IconButtonShapes

the IconButtonShapes that the icon toggle button will morph between depending on the user's interaction with the icon toggle button.

modifier: Modifier = Modifier

the Modifier to be applied to this icon button

enabled: Boolean = true

controls the enabled state of this icon button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

colors: IconToggleButtonColors = IconButtonDefaults.iconToggleButtonVibrantColors()

IconToggleButtonColors that will be used to resolve the colors used for this icon button in different states. See IconButtonDefaults.iconToggleButtonVibrantColors.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this icon button. You can use this to change the icon button's appearance or preview the icon button in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable () -> Unit

the content of this icon button, typically an Icon

InputChip

@Composable
fun InputChip(
    selected: Boolean,
    onClick: () -> Unit,
    label: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    leadingIcon: (@Composable () -> Unit)? = null,
    avatar: (@Composable () -> Unit)? = null,
    trailingIcon: (@Composable () -> Unit)? = null,
    shape: Shape = InputChipDefaults.shape,
    colors: SelectableChipColors = InputChipDefaults.inputChipColors(),
    elevation: SelectableChipElevation? = InputChipDefaults.inputChipElevation(),
    border: BorderStroke? = InputChipDefaults.inputChipBorder(enabled, selected),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design input chip.

Chips help people enter information, make selections, filter content, or trigger actions. Chips can show multiple interactive elements together in the same area, such as a list of selectable movie times, or a series of email contacts.

Input chips represent discrete pieces of information entered by a user.

Input chip image

An Input Chip can have a leading icon or an avatar at its start. In case both are provided, the avatar will take precedence and will be displayed.

Example of an InputChip with a trailing icon:

import androidx.compose.material3.InputChip
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var selected by remember { mutableStateOf(false) }
InputChip(
    selected = selected,
    onClick = { selected = !selected },
    label = { Text("Input Chip") },
)

Example of an InputChip with an avatar and a trailing icon:

import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Person
import androidx.compose.material3.Icon
import androidx.compose.material3.InputChip
import androidx.compose.material3.InputChipDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier

var selected by remember { mutableStateOf(false) }
InputChip(
    selected = selected,
    onClick = { selected = !selected },
    label = { Text("Input Chip") },
    avatar = {
        Icon(
            Icons.Filled.Person,
            contentDescription = "Localized description",
            Modifier.size(InputChipDefaults.AvatarSize)
        )
    }
)

Input chips should appear in a set and can be horizontally scrollable:

import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.material3.AssistChip
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

Column(horizontalAlignment = Alignment.CenterHorizontally) {
    Row(modifier = Modifier.horizontalScroll(rememberScrollState())) {
        repeat(9) { index ->
            AssistChip(
                modifier = Modifier.padding(horizontal = 4.dp),
                onClick = { /* do something*/ },
                label = { Text("Chip $index") }
            )
        }
    }
}

Alternatively, use androidx.compose.foundation.layout.FlowRow to wrap chips to a new line.

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.material3.AssistChip
import androidx.compose.material3.Text
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastForEachIndexed

val colorNames =
    listOf(
        "Blue",
        "Yellow",
        "Red",
        "Orange",
        "Black",
        "Green",
        "White",
        "Magenta",
        "Gray",
        "Transparent"
    )
Column {
    FlowRow(
        Modifier.fillMaxWidth(1f).wrapContentHeight(align = Alignment.Top),
        horizontalArrangement = Arrangement.Start,
    ) {
        colorNames.fastForEachIndexed { index, element ->
            AssistChip(
                modifier =
                    Modifier.padding(horizontal = 4.dp)
                        .align(alignment = Alignment.CenterVertically),
                onClick = { /* do something*/ },
                label = { Text("$element $index") }
            )
        }
    }
}
Parameters
selected: Boolean

whether this chip is selected or not

onClick: () -> Unit

called when this chip is clicked

label: @Composable () -> Unit

text label for this chip

modifier: Modifier = Modifier

the Modifier to be applied to this chip

enabled: Boolean = true

controls the enabled state of this chip. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

leadingIcon: (@Composable () -> Unit)? = null

optional icon at the start of the chip, preceding the label text

avatar: (@Composable () -> Unit)? = null

optional avatar at the start of the chip, preceding the label text

trailingIcon: (@Composable () -> Unit)? = null

optional icon at the end of the chip

shape: Shape = InputChipDefaults.shape

defines the shape of this chip's container, border (when border is not null), and shadow (when using elevation)

colors: SelectableChipColors = InputChipDefaults.inputChipColors()

ChipColors that will be used to resolve the colors used for this chip in different states. See InputChipDefaults.inputChipColors.

elevation: SelectableChipElevation? = InputChipDefaults.inputChipElevation()

ChipElevation used to resolve the elevation for this chip in different states. This controls the size of the shadow below the chip. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See InputChipDefaults.inputChipElevation.

border: BorderStroke? = InputChipDefaults.inputChipBorder(enabled, selected)

the border to draw around the container of this chip. Pass null for no border. See InputChipDefaults.inputChipBorder.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this chip. You can use this to change the chip's appearance or preview the chip in different states. Note that if null is provided, interactions will still happen internally.

@ExperimentalMaterial3Api
@Composable
fun Label(
    label: @Composable TooltipScope.() -> Unit,
    modifier: Modifier = Modifier,
    interactionSource: MutableInteractionSource? = null,
    isPersistent: Boolean = false,
    content: @Composable () -> Unit
): Unit

Label component that will append a label to content. The positioning logic uses TooltipDefaults.rememberTooltipPositionProvider.

Label appended to thumbs of Slider:

import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.Label
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

var sliderPosition by remember { mutableStateOf(0f) }
val interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    Slider(
        modifier = Modifier.semantics { contentDescription = "Localized Description" },
        value = sliderPosition,
        onValueChange = { sliderPosition = it },
        valueRange = 0f..100f,
        interactionSource = interactionSource,
        onValueChangeFinished = {
            // launch some business logic update with the state you hold
            // viewModel.updateSelectedSliderValue(sliderPosition)
        },
        thumb = {
            Label(
                label = {
                    PlainTooltip(modifier = Modifier.sizeIn(45.dp, 25.dp).wrapContentWidth()) {
                        Text("%.2f".format(sliderPosition))
                    }
                },
                interactionSource = interactionSource
            ) {
                Icon(
                    imageVector = Icons.Filled.Favorite,
                    contentDescription = null,
                    modifier = Modifier.size(ButtonDefaults.IconSize),
                    tint = Color.Red
                )
            }
        }
    )
}

Label appended to thumbs of RangeSlider:

import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.material3.Label
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.RangeSlider
import androidx.compose.material3.RangeSliderState
import androidx.compose.material3.Slider
import androidx.compose.material3.SliderDefaults
import androidx.compose.material3.SliderState
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

val rangeSliderState = remember {
    RangeSliderState(
        0f,
        100f,
        valueRange = 0f..100f,
        onValueChangeFinished = {
            // launch some business logic update with the state you hold
            // viewModel.updateSelectedSliderValue(sliderPosition)
        }
    )
}
val startInteractionSource = remember { MutableInteractionSource() }
val endInteractionSource = remember { MutableInteractionSource() }
val startThumbAndTrackColors =
    SliderDefaults.colors(thumbColor = Color.Blue, activeTrackColor = Color.Red)
val endThumbColors = SliderDefaults.colors(thumbColor = Color.Green)
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    RangeSlider(
        state = rangeSliderState,
        modifier = Modifier.semantics { contentDescription = "Localized Description" },
        startInteractionSource = startInteractionSource,
        endInteractionSource = endInteractionSource,
        startThumb = {
            Label(
                label = {
                    PlainTooltip(modifier = Modifier.sizeIn(45.dp, 25.dp).wrapContentWidth()) {
                        Text("%.2f".format(rangeSliderState.activeRangeStart))
                    }
                },
                interactionSource = startInteractionSource
            ) {
                SliderDefaults.Thumb(
                    interactionSource = startInteractionSource,
                    colors = startThumbAndTrackColors
                )
            }
        },
        endThumb = {
            Label(
                label = {
                    PlainTooltip(
                        modifier = Modifier.requiredSize(45.dp, 25.dp).wrapContentWidth()
                    ) {
                        Text("%.2f".format(rangeSliderState.activeRangeEnd))
                    }
                },
                interactionSource = endInteractionSource
            ) {
                SliderDefaults.Thumb(
                    interactionSource = endInteractionSource,
                    colors = endThumbColors
                )
            }
        },
        track = { rangeSliderState ->
            SliderDefaults.Track(
                colors = startThumbAndTrackColors,
                rangeSliderState = rangeSliderState
            )
        }
    )
}
Parameters
label: @Composable TooltipScope.() -> Unit

composable that will be appended to content

modifier: Modifier = Modifier

Modifier that will be applied to content

interactionSource: MutableInteractionSource? = null

the MutableInteractionSource representing the stream of Interactions for the content.

isPersistent: Boolean = false

boolean to determine if the label should be persistent. If true, then the label will always show and be anchored to content. if false, then the label will only show when pressing down or hovering over the content.

content: @Composable () -> Unit

the composable that label will anchor to.

LargeExtendedFloatingActionButton

@ExperimentalMaterial3ExpressiveApi
@Composable
fun LargeExtendedFloatingActionButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    shape: Shape = FloatingActionButtonDefaults.largeExtendedFabShape,
    containerColor: Color = FloatingActionButtonDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable RowScope.() -> Unit
): Unit

Material Design large extended floating action button.

Extended FABs help people take primary actions. They're wider than FABs to accommodate a text label and larger target area.

The other large extended floating action button overload supports a text label and icon.

import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.LargeExtendedFloatingActionButton
import androidx.compose.material3.Text

LargeExtendedFloatingActionButton(onClick = { /* do something */ }) {
    Text(text = "Large Extended FAB")
}
Parameters
onClick: () -> Unit

called when this FAB is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this FAB

shape: Shape = FloatingActionButtonDefaults.largeExtendedFabShape

defines the shape of this FAB's container and shadow (when using elevation)

containerColor: Color = FloatingActionButtonDefaults.containerColor

the color used for the background of this FAB. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this FAB. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation()

FloatingActionButtonElevation used to resolve the elevation for this FAB in different states. This controls the size of the shadow below the FAB. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See also: Surface.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this FAB. You can use this to change the FAB's appearance or preview the FAB in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable RowScope.() -> Unit

the content of this FAB, typically a Text label

LargeExtendedFloatingActionButton

@ExperimentalMaterial3ExpressiveApi
@Composable
fun LargeExtendedFloatingActionButton(
    text: @Composable () -> Unit,
    icon: @Composable () -> Unit,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    expanded: Boolean = true,
    shape: Shape = FloatingActionButtonDefaults.largeExtendedFabShape,
    containerColor: Color = FloatingActionButtonDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design large extended floating action button.

Extended FABs help people take primary actions. They're wider than FABs to accommodate a text label and larger target area.

The other large extended floating action button overload is for FABs without an icon.

Default content description for accessibility is extended from the extended fabs icon. For custom behavior, you can provide your own via Modifier.semantics.

import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.LargeExtendedFloatingActionButton
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier

LargeExtendedFloatingActionButton(
    onClick = { /* do something */ },
    icon = {
        Icon(
            Icons.Filled.Add,
            "Localized description",
            modifier = Modifier.size(FloatingActionButtonDefaults.LargeIconSize)
        )
    },
    text = { Text(text = "Large Extended FAB") },
)
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FabPosition
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.LargeExtendedFloatingActionButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val listState = rememberLazyListState()
// The FAB is initially expanded. Once the first visible item is past the first item we
// collapse the FAB. We use a remembered derived state to minimize unnecessary compositions.
val expandedFab by remember { derivedStateOf { listState.firstVisibleItemIndex == 0 } }
Scaffold(
    floatingActionButton = {
        LargeExtendedFloatingActionButton(
            onClick = { /* do something */ },
            expanded = expandedFab,
            icon = {
                Icon(
                    Icons.Filled.Add,
                    "Localized Description",
                    modifier = Modifier.size(FloatingActionButtonDefaults.LargeIconSize)
                )
            },
            text = { Text(text = "Large Extended FAB") },
        )
    },
    floatingActionButtonPosition = FabPosition.End,
) {
    LazyColumn(state = listState, modifier = Modifier.fillMaxSize()) {
        for (index in 0 until 100) {
            item { Text(text = "List item - $index", modifier = Modifier.padding(24.dp)) }
        }
    }
}
Parameters
text: @Composable () -> Unit

label displayed inside this FAB

icon: @Composable () -> Unit

icon for this FAB, typically an Icon

onClick: () -> Unit

called when this FAB is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this FAB

expanded: Boolean = true

controls the expansion state of this FAB. In an expanded state, the FAB will show both the icon and text. In a collapsed state, the FAB will show only the icon.

shape: Shape = FloatingActionButtonDefaults.largeExtendedFabShape

defines the shape of this FAB's container and shadow (when using elevation)

containerColor: Color = FloatingActionButtonDefaults.containerColor

the color used for the background of this FAB. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this FAB. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation()

FloatingActionButtonElevation used to resolve the elevation for this FAB in different states. This controls the size of the shadow below the FAB. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See also: Surface.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this FAB. You can use this to change the FAB's appearance or preview the FAB in different states. Note that if null is provided, interactions will still happen internally.

LargeFloatingActionButton

@Composable
fun LargeFloatingActionButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    shape: Shape = FloatingActionButtonDefaults.largeShape,
    containerColor: Color = FloatingActionButtonDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable () -> Unit
): Unit

Material Design large floating action button.

The FAB represents the most important action on a screen. It puts key actions within reach.

Large FAB image

import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.LargeFloatingActionButton
import androidx.compose.ui.Modifier

LargeFloatingActionButton(
    onClick = { /* do something */ },
) {
    Icon(
        Icons.Filled.Add,
        contentDescription = "Localized description",
        modifier = Modifier.size(FloatingActionButtonDefaults.LargeIconSize),
    )
}

FABs can also be shown and hidden with an animation when the main content is scrolled:

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FabPosition
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MediumFloatingActionButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.animateFloatingActionButton
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val listState = rememberLazyListState()
// The FAB is initially shown. Upon scrolling past the first item we hide the FAB by using a
// remembered derived state to minimize unnecessary compositions.
val fabVisible by remember { derivedStateOf { listState.firstVisibleItemIndex == 0 } }

Scaffold(
    floatingActionButton = {
        MediumFloatingActionButton(
            modifier =
                Modifier.animateFloatingActionButton(
                    visible = fabVisible,
                    alignment = Alignment.BottomEnd
                ),
            onClick = { /* do something */ },
        ) {
            Icon(
                Icons.Filled.Add,
                contentDescription = "Localized description",
                modifier = Modifier.size(FloatingActionButtonDefaults.MediumIconSize),
            )
        }
    },
    floatingActionButtonPosition = FabPosition.End,
) {
    LazyColumn(state = listState, modifier = Modifier.fillMaxSize()) {
        for (index in 0 until 100) {
            item { Text(text = "List item - $index", modifier = Modifier.padding(24.dp)) }
        }
    }
}
Parameters
onClick: () -> Unit

called when this FAB is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this FAB

shape: Shape = FloatingActionButtonDefaults.largeShape

defines the shape of this FAB's container and shadow (when using elevation)

containerColor: Color = FloatingActionButtonDefaults.containerColor

the color used for the background of this FAB. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this FAB. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation()

FloatingActionButtonElevation used to resolve the elevation for this FAB in different states. This controls the size of the shadow below the FAB. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See also: Surface.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this FAB. You can use this to change the FAB's appearance or preview the FAB in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable () -> Unit

the content of this FAB, typically an Icon

LargeTopAppBar

@ExperimentalMaterial3Api
@Composable
fun LargeTopAppBar(
    title: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    navigationIcon: @Composable () -> Unit = {},
    actions: @Composable RowScope.() -> Unit = {},
    collapsedHeight: Dp = TopAppBarDefaults.LargeAppBarCollapsedHeight,
    expandedHeight: Dp = TopAppBarDefaults.LargeAppBarExpandedHeight,
    windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
    colors: TopAppBarColors = TopAppBarDefaults.largeTopAppBarColors(),
    scrollBehavior: TopAppBarScrollBehavior? = null
): Unit

Material Design large top app bar.

Top app bars display information and actions at the top of a screen.

Large top app bar image

This LargeTopAppBar has slots for a title, navigation icon, and actions. In its default expanded state, the title is displayed in a second row under the navigation and actions.

A large top app bar that uses a scrollBehavior to customize its nested scrolling behavior when working in conjunction with scrolling content looks like:

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LargeTopAppBar
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp

val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    topBar = {
        LargeTopAppBar(
            title = { Text("Large TopAppBar", maxLines = 1, overflow = TextOverflow.Ellipsis) },
            navigationIcon = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Menu,
                        contentDescription = "Localized description"
                    )
                }
            },
            actions = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Favorite,
                        contentDescription = "Localized description"
                    )
                }
            },
            scrollBehavior = scrollBehavior
        )
    },
    content = { innerPadding ->
        LazyColumn(
            contentPadding = innerPadding,
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            val list = (0..75).map { it.toString() }
            items(count = list.size) {
                Text(
                    text = list[it],
                    style = MaterialTheme.typography.bodyLarge,
                    modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                )
            }
        }
    }
)
Parameters
title: @Composable () -> Unit

the title to be displayed in the top app bar. This title will be used in the app bar's expanded and collapsed states, although in its collapsed state it will be composed with a smaller sized TextStyle

modifier: Modifier = Modifier

the Modifier to be applied to this top app bar

navigationIcon: @Composable () -> Unit = {}

the navigation icon displayed at the start of the top app bar. This should typically be an IconButton or IconToggleButton.

actions: @Composable RowScope.() -> Unit = {}

the actions displayed at the end of the top app bar. This should typically be IconButtons. The default layout here is a Row, so icons inside will be placed horizontally.

collapsedHeight: Dp = TopAppBarDefaults.LargeAppBarCollapsedHeight

this app bar height when collapsed by a provided scrollBehavior. This value must be specified and finite, otherwise it will be ignored and replaced with TopAppBarDefaults.LargeAppBarCollapsedHeight.

expandedHeight: Dp = TopAppBarDefaults.LargeAppBarExpandedHeight

this app bar's maximum height. When a specified scrollBehavior causes the app bar to collapse or expand, this value will represent the maximum height that the app-bar will be allowed to expand. The expanded height is expected to be greater or equal to the collapsedHeight, and the function will throw an IllegalArgumentException otherwise. Also, this value must be specified and finite, otherwise it will be ignored and replaced with TopAppBarDefaults.LargeAppBarExpandedHeight.

windowInsets: WindowInsets = TopAppBarDefaults.windowInsets

a window insets that app bar will respect.

colors: TopAppBarColors = TopAppBarDefaults.largeTopAppBarColors()

TopAppBarColors that will be used to resolve the colors used for this top app bar in different states. See TopAppBarDefaults.largeTopAppBarColors.

scrollBehavior: TopAppBarScrollBehavior? = null

a TopAppBarScrollBehavior which holds various offset values that will be applied by this top app bar to set up its height and colors. A scroll behavior is designed to work in conjunction with a scrolled content to change the top app bar appearance as the content scrolls. See TopAppBarScrollBehavior.nestedScrollConnection.

Throws
kotlin.IllegalArgumentException

if the provided expandedHeight is smaller to the collapsedHeight

LargeTopAppBar

@ExperimentalMaterial3ExpressiveApi
@Composable
fun LargeTopAppBar(
    title: @Composable () -> Unit,
    subtitle: (@Composable () -> Unit)?,
    modifier: Modifier = Modifier,
    navigationIcon: @Composable () -> Unit = {},
    actions: @Composable RowScope.() -> Unit = {},
    titleHorizontalAlignment: TopAppBarTitleAlignment = TopAppBarTitleAlignment.Start,
    collapsedHeight: Dp = TopAppBarDefaults.LargeAppBarCollapsedHeight,
    expandedHeight: Dp = if (subtitle != null) { TopAppBarDefaults.LargeAppBarWithSubtitleExpandedHeight } else { TopAppBarDefaults.LargeAppBarWithoutSubtitleExpandedHeight },
    windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
    colors: TopAppBarColors = TopAppBarDefaults.largeTopAppBarColors(),
    scrollBehavior: TopAppBarScrollBehavior? = null
): Unit

Material Design large top app bar.

Top app bars display information and actions at the top of a screen.

Large top app bar image

This LargeTopAppBar has slots for a title, subtitle, navigation icon, and actions. In its default expanded state, the title and subtitle are displayed in a second row under the navigation and actions.

A large top app bar that uses a scrollBehavior to customize its nested scrolling behavior when working in conjunction with scrolling content looks like:

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LargeTopAppBar
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarTitleAlignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp

val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    topBar = {
        LargeTopAppBar(
            title = { Text("Large TopAppBar", maxLines = 1, overflow = TextOverflow.Ellipsis) },
            subtitle = { Text("Subtitle", maxLines = 1, overflow = TextOverflow.Ellipsis) },
            titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
            navigationIcon = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Menu,
                        contentDescription = "Localized description"
                    )
                }
            },
            actions = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Favorite,
                        contentDescription = "Localized description"
                    )
                }
            },
            scrollBehavior = scrollBehavior
        )
    },
    content = { innerPadding ->
        LazyColumn(
            contentPadding = innerPadding,
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            val list = (0..75).map { it.toString() }
            items(count = list.size) {
                Text(
                    text = list[it],
                    style = MaterialTheme.typography.bodyLarge,
                    modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                )
            }
        }
    }
)
Parameters
title: @Composable () -> Unit

the title to be displayed in the top app bar. This title will be used in the app bar's expanded and collapsed states, although in its collapsed state it will be composed with a smaller sized TextStyle

subtitle: (@Composable () -> Unit)?

the subtitle to be displayed in the top app bar. This subtitle will be used in the app bar's expanded and collapsed states

modifier: Modifier = Modifier

the Modifier to be applied to this top app bar

navigationIcon: @Composable () -> Unit = {}

the navigation icon displayed at the start of the top app bar. This should typically be an IconButton or IconToggleButton.

actions: @Composable RowScope.() -> Unit = {}

the actions displayed at the end of the top app bar. This should typically be IconButtons. The default layout here is a Row, so icons inside will be placed horizontally.

titleHorizontalAlignment: TopAppBarTitleAlignment = TopAppBarTitleAlignment.Start

the horizontal alignment of the title and subtitle

collapsedHeight: Dp = TopAppBarDefaults.LargeAppBarCollapsedHeight

this app bar height when collapsed by a provided scrollBehavior. This value must be specified and finite, otherwise it will be ignored and replaced with TopAppBarDefaults.LargeAppBarCollapsedHeight.

expandedHeight: Dp = if (subtitle != null) { TopAppBarDefaults.LargeAppBarWithSubtitleExpandedHeight } else { TopAppBarDefaults.LargeAppBarWithoutSubtitleExpandedHeight }

this app bar's maximum height. When a specified scrollBehavior causes the app bar to collapse or expand, this value will represent the maximum height that the app-bar will be allowed to expand. The expanded height is expected to be greater or equal to the collapsedHeight, and the function will throw an IllegalArgumentException otherwise. Also, this value must be specified and finite, otherwise it will be ignored and replaced with TopAppBarDefaults.LargeAppBarExpandedHeight.

windowInsets: WindowInsets = TopAppBarDefaults.windowInsets

a window insets that app bar will respect.

colors: TopAppBarColors = TopAppBarDefaults.largeTopAppBarColors()

TopAppBarColors that will be used to resolve the colors used for this top app bar in different states. See TopAppBarDefaults.largeTopAppBarColors.

scrollBehavior: TopAppBarScrollBehavior? = null

a TopAppBarScrollBehavior which holds various offset values that will be applied by this top app bar to set up its height and colors. A scroll behavior is designed to work in conjunction with a scrolled content to change the top app bar appearance as the content scrolls. See TopAppBarScrollBehavior.nestedScrollConnection.

Throws
kotlin.IllegalArgumentException

if the provided expandedHeight is smaller to the collapsedHeight

LeadingIconTab

@Composable
fun LeadingIconTab(
    selected: Boolean,
    onClick: () -> Unit,
    text: @Composable () -> Unit,
    icon: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    selectedContentColor: Color = LocalContentColor.current,
    unselectedContentColor: Color = selectedContentColor,
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design tab.

Tabs organize content across different screens, data sets, and other interactions.

A LeadingIconTab represents a single page of content using a text label and an icon in front of the label. It represents its selected state by tinting the text label and icon with selectedContentColor.

This should typically be used inside of a TabRow, see the corresponding documentation for example usage.

Parameters
selected: Boolean

whether this tab is selected or not

onClick: () -> Unit

called when this tab is clicked

text: @Composable () -> Unit

the text label displayed in this tab

icon: @Composable () -> Unit

the icon displayed in this tab. Should be 24.dp.

modifier: Modifier = Modifier

the Modifier to be applied to this tab

enabled: Boolean = true

controls the enabled state of this tab. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

selectedContentColor: Color = LocalContentColor.current

the color for the content of this tab when selected, and the color of the ripple.

unselectedContentColor: Color = selectedContentColor

the color for the content of this tab when not selected

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this tab. You can use this to change the tab's appearance or preview the tab in different states. Note that if null is provided, interactions will still happen internally.

See also
Tab

LinearProgressIndicator

@Composable
fun LinearProgressIndicator(
    modifier: Modifier = Modifier,
    color: Color = ProgressIndicatorDefaults.linearColor,
    trackColor: Color = ProgressIndicatorDefaults.linearTrackColor,
    strokeCap: StrokeCap = ProgressIndicatorDefaults.LinearStrokeCap,
    gapSize: Dp = ProgressIndicatorDefaults.LinearIndicatorTrackGapSize
): Unit

Indeterminate Material Design linear progress indicator.

Progress indicators express an unspecified wait time or display the duration of a process.

Linear progress indicator image

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.ui.Alignment

Column(horizontalAlignment = Alignment.CenterHorizontally) { LinearProgressIndicator() }
Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this progress indicator

color: Color = ProgressIndicatorDefaults.linearColor

color of this progress indicator

trackColor: Color = ProgressIndicatorDefaults.linearTrackColor

color of the track behind the indicator, visible when the progress has not reached the area of the overall indicator yet

strokeCap: StrokeCap = ProgressIndicatorDefaults.LinearStrokeCap

stroke cap to use for the ends of this progress indicator

gapSize: Dp = ProgressIndicatorDefaults.LinearIndicatorTrackGapSize

size of the gap between the progress indicator and the track

LinearProgressIndicator

@Composable
fun LinearProgressIndicator(
    progress: Float,
    modifier: Modifier = Modifier,
    color: Color = ProgressIndicatorDefaults.linearColor,
    trackColor: Color = ProgressIndicatorDefaults.linearTrackColor,
    strokeCap: StrokeCap = ProgressIndicatorDefaults.LinearStrokeCap
): Unit

LinearProgressIndicator

@Composable
fun LinearProgressIndicator(
    progress: () -> Float,
    modifier: Modifier = Modifier,
    color: Color = ProgressIndicatorDefaults.linearColor,
    trackColor: Color = ProgressIndicatorDefaults.linearTrackColor,
    strokeCap: StrokeCap = ProgressIndicatorDefaults.LinearStrokeCap,
    gapSize: Dp = ProgressIndicatorDefaults.LinearIndicatorTrackGapSize,
    drawStopIndicator: DrawScope.() -> Unit = { drawStopIndicator( drawScope = this, stopSize = ProgressIndicatorDefaults.LinearTrackStopIndicatorSize, color = color, strokeCap = strokeCap ) }
): Unit

Determinate Material Design linear progress indicator.

Progress indicators express an unspecified wait time or display the duration of a process.

Linear progress indicator image

By default there is no animation between progress values. You can use ProgressIndicatorDefaults.ProgressAnimationSpec as the default recommended AnimationSpec when animating progress, such as in the following example:

import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.width
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.ProgressIndicatorDefaults
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

var progress by remember { mutableFloatStateOf(0.1f) }
val animatedProgress by
    animateFloatAsState(
        targetValue = progress,
        animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
    )

Column(horizontalAlignment = Alignment.CenterHorizontally) {
    LinearProgressIndicator(
        progress = { animatedProgress },
    )
    Spacer(Modifier.requiredHeight(30.dp))
    Text("Set progress:")
    Slider(
        modifier = Modifier.width(300.dp),
        value = progress,
        valueRange = 0f..1f,
        onValueChange = { progress = it },
    )
}
Parameters
progress: () -> Float

the progress of this progress indicator, where 0.0 represents no progress and 1.0 represents full progress. Values outside of this range are coerced into the range.

modifier: Modifier = Modifier

the Modifier to be applied to this progress indicator

color: Color = ProgressIndicatorDefaults.linearColor

color of this progress indicator

trackColor: Color = ProgressIndicatorDefaults.linearTrackColor

color of the track behind the indicator, visible when the progress has not reached the area of the overall indicator yet

strokeCap: StrokeCap = ProgressIndicatorDefaults.LinearStrokeCap

stroke cap to use for the ends of this progress indicator

gapSize: Dp = ProgressIndicatorDefaults.LinearIndicatorTrackGapSize

size of the gap between the progress indicator and the track

drawStopIndicator: DrawScope.() -> Unit = { drawStopIndicator( drawScope = this, stopSize = ProgressIndicatorDefaults.LinearTrackStopIndicatorSize, color = color, strokeCap = strokeCap ) }

lambda that will be called to draw the stop indicator

LinearWavyProgressIndicator

@ExperimentalMaterial3ExpressiveApi
@Composable
fun LinearWavyProgressIndicator(
    modifier: Modifier = Modifier,
    color: Color = WavyProgressIndicatorDefaults.indicatorColor,
    trackColor: Color = WavyProgressIndicatorDefaults.trackColor,
    stroke: Stroke = WavyProgressIndicatorDefaults.linearIndicatorStroke,
    trackStroke: Stroke = WavyProgressIndicatorDefaults.linearTrackStroke,
    gapSize: Dp = WavyProgressIndicatorDefaults.LinearIndicatorTrackGapSize,
    amplitude: @FloatRange(from = 0.0, to = 1.0) Float = 1.0f,
    wavelength: Dp = WavyProgressIndicatorDefaults.LinearIndeterminateWavelength,
    waveSpeed: Dp = wavelength
): Unit

Indeterminate Material Design linear wavy progress indicator.

Progress indicators express an unspecified wait time or display the duration of a process.

Indeterminate linear wavy progress indicator image

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.LinearWavyProgressIndicator
import androidx.compose.ui.Alignment

Column(horizontalAlignment = Alignment.CenterHorizontally) { LinearWavyProgressIndicator() }
Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this progress indicator

color: Color = WavyProgressIndicatorDefaults.indicatorColor

the progress indicator color

trackColor: Color = WavyProgressIndicatorDefaults.trackColor

the indicator's track color, visible when the progress has not reached the area of the overall indicator yet

stroke: Stroke = WavyProgressIndicatorDefaults.linearIndicatorStroke

a Stroke that will be used to draw this indicator

trackStroke: Stroke = WavyProgressIndicatorDefaults.linearTrackStroke

a Stroke that will be used to draw the indicator's track

gapSize: Dp = WavyProgressIndicatorDefaults.LinearIndicatorTrackGapSize

the gap between the track and the progress parts of the indicator

amplitude: @FloatRange(from = 0.0, to = 1.0) Float = 1.0f

the wave's amplitude. 0.0 represents no amplitude, and 1.0 represents an amplitude that will take the full height of the progress indicator. Values outside of this range are coerced into the range.

wavelength: Dp = WavyProgressIndicatorDefaults.LinearIndeterminateWavelength

the length of a wave

waveSpeed: Dp = wavelength

the speed in which the wave will move when the amplitude is greater than zero. The value here represents a DP per seconds, and by default it's matched to the wavelength to render an animation that moves the wave by one wave length per second.

LinearWavyProgressIndicator

@ExperimentalMaterial3ExpressiveApi
@Composable
fun LinearWavyProgressIndicator(
    progress: () -> Float,
    modifier: Modifier = Modifier,
    color: Color = WavyProgressIndicatorDefaults.indicatorColor,
    trackColor: Color = WavyProgressIndicatorDefaults.trackColor,
    stroke: Stroke = WavyProgressIndicatorDefaults.linearIndicatorStroke,
    trackStroke: Stroke = WavyProgressIndicatorDefaults.linearTrackStroke,
    gapSize: Dp = WavyProgressIndicatorDefaults.LinearIndicatorTrackGapSize,
    stopSize: Dp = WavyProgressIndicatorDefaults.LinearTrackStopIndicatorSize,
    amplitude: (progress: Float) -> Float = WavyProgressIndicatorDefaults.indicatorAmplitude,
    wavelength: Dp = WavyProgressIndicatorDefaults.LinearDeterminateWavelength,
    waveSpeed: Dp = wavelength
): Unit

Determinate Material Design wavy linear progress indicator.

Progress indicators express an unspecified wait time or display the duration of a process.

Linear wavy progress indicator image

This version of a linear progress indicator accepts arguments, such as amplitude, wavelength, and waveSpeed to render the progress as a waveform.

By default there is no animation between progress values. You can use WavyProgressIndicatorDefaults.ProgressAnimationSpec as the default recommended AnimationSpec when animating progress, such as in the following example:

import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.width
import androidx.compose.material3.LinearWavyProgressIndicator
import androidx.compose.material3.ProgressIndicatorDefaults
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

var progress by remember { mutableFloatStateOf(0.1f) }
val animatedProgress by
    animateFloatAsState(
        targetValue = progress,
        animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
    )

Column(horizontalAlignment = Alignment.CenterHorizontally) {
    LinearWavyProgressIndicator(
        progress = { animatedProgress },
    )
    Spacer(Modifier.requiredHeight(30.dp))
    Text("Set progress:")
    Slider(
        modifier = Modifier.width(300.dp),
        value = progress,
        valueRange = 0f..1f,
        onValueChange = { progress = it },
    )
}

You may also follow the Material guidelines to create a thicker version of this indicator, like in this example:

import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.width
import androidx.compose.material3.LinearWavyProgressIndicator
import androidx.compose.material3.ProgressIndicatorDefaults
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp

var progress by remember { mutableFloatStateOf(0.1f) }
val animatedProgress by
    animateFloatAsState(
        targetValue = progress,
        animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
    )

val thickStrokeWidth = with(LocalDensity.current) { 8.dp.toPx() }
val thickStroke =
    remember(thickStrokeWidth) { Stroke(width = thickStrokeWidth, cap = StrokeCap.Round) }

Column(horizontalAlignment = Alignment.CenterHorizontally) {
    LinearWavyProgressIndicator(
        progress = { animatedProgress },
        // Thick height is slightly higher than the
        // WavyProgressIndicatorDefaults.LinearContainerHeight default
        modifier = Modifier.height(14.dp),
        stroke = thickStroke,
        trackStroke = thickStroke,
    )
    Spacer(Modifier.requiredHeight(30.dp))
    Text("Set progress:")
    Slider(
        modifier = Modifier.width(300.dp),
        value = progress,
        valueRange = 0f..1f,
        onValueChange = { progress = it },
    )
}
Parameters
progress: Float

the progress of this progress indicator, where 0.0 represents no progress and 1.0 represents full progress. Values outside of this range are coerced into the range.

modifier: Modifier = Modifier

the Modifier to be applied to this progress indicator

color: Color = WavyProgressIndicatorDefaults.indicatorColor

the progress indicator color

trackColor: Color = WavyProgressIndicatorDefaults.trackColor

the indicator's track color, visible when the progress has not reached the area of the overall indicator yet

stroke: Stroke = WavyProgressIndicatorDefaults.linearIndicatorStroke

a Stroke that will be used to draw this indicator

trackStroke: Stroke = WavyProgressIndicatorDefaults.linearTrackStroke

a Stroke that will be used to draw the indicator's track

gapSize: Dp = WavyProgressIndicatorDefaults.LinearIndicatorTrackGapSize

the gap between the track and the progress parts of the indicator

stopSize: Dp = WavyProgressIndicatorDefaults.LinearTrackStopIndicatorSize

the size of the stop indicator at the end of the track. Note that the stop indicator is required if the track has a contrast below 3:1 with its container or the surface behind the container.

amplitude: (progress: Float) -> Float = WavyProgressIndicatorDefaults.indicatorAmplitude

a lambda that provides an amplitude for the wave path as a function of the indicator's progress. 0.0 represents no amplitude, and 1.0 represents an amplitude that will take the full height of the progress indicator. Values outside of this range are coerced into the range.

wavelength: Dp = WavyProgressIndicatorDefaults.LinearDeterminateWavelength

the length of a wave. Will be applied in case the path has an amplitude that is greater than zero and represents a wave.

waveSpeed: Dp = wavelength

the speed in which the wave will move when the amplitude is greater than zero. The value here represents a DP per seconds, and by default it's matched to the wavelength to render an animation that moves the wave by one wave length per second.

@Composable
fun ListItem(
    headlineContent: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    overlineContent: (@Composable () -> Unit)? = null,
    supportingContent: (@Composable () -> Unit)? = null,
    leadingContent: (@Composable () -> Unit)? = null,
    trailingContent: (@Composable () -> Unit)? = null,
    colors: ListItemColors = ListItemDefaults.colors(),
    tonalElevation: Dp = ListItemDefaults.Elevation,
    shadowElevation: Dp = ListItemDefaults.Elevation
): Unit

Material Design list item.

Lists are continuous, vertical indexes of text or images.

Lists image

This component can be used to achieve the list item templates existing in the spec. One-line list items have a singular line of headline content. Two-line list items additionally have either supporting or overline content. Three-line list items have either both supporting and overline content, or extended (two-line) supporting text. For example:

  • one-line item

import androidx.compose.foundation.layout.Column
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.Text

Column {
    ListItem(
        headlineContent = { Text("One line list item with 24x24 icon") },
        leadingContent = {
            Icon(
                Icons.Filled.Favorite,
                contentDescription = "Localized description",
            )
        }
    )
    HorizontalDivider()
}
  • two-line item

import androidx.compose.foundation.layout.Column
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.Text

Column {
    ListItem(
        headlineContent = { Text("Two line list item with trailing") },
        supportingContent = { Text("Secondary text") },
        trailingContent = { Text("meta") },
        leadingContent = {
            Icon(
                Icons.Filled.Favorite,
                contentDescription = "Localized description",
            )
        }
    )
    HorizontalDivider()
}
  • three-line item with both overline and supporting content

import androidx.compose.foundation.layout.Column
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.Text

Column {
    ListItem(
        headlineContent = { Text("Three line list item") },
        overlineContent = { Text("OVERLINE") },
        supportingContent = { Text("Secondary text") },
        leadingContent = {
            Icon(
                Icons.Filled.Favorite,
                contentDescription = "Localized description",
            )
        },
        trailingContent = { Text("meta") }
    )
    HorizontalDivider()
}
  • three-line item with extended supporting content

import androidx.compose.foundation.layout.Column
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.Text

Column {
    ListItem(
        headlineContent = { Text("Three line list item") },
        supportingContent = {
            Text("Secondary text that is long and perhaps goes onto another line")
        },
        leadingContent = {
            Icon(
                Icons.Filled.Favorite,
                contentDescription = "Localized description",
            )
        },
        trailingContent = { Text("meta") }
    )
    HorizontalDivider()
}
Parameters
headlineContent: @Composable () -> Unit

the headline content of the list item

modifier: Modifier = Modifier

Modifier to be applied to the list item

overlineContent: (@Composable () -> Unit)? = null

the content displayed above the headline content

supportingContent: (@Composable () -> Unit)? = null

the supporting content of the list item

leadingContent: (@Composable () -> Unit)? = null

the leading content of the list item

trailingContent: (@Composable () -> Unit)? = null

the trailing meta text, icon, switch or checkbox

colors: ListItemColors = ListItemDefaults.colors()

ListItemColors that will be used to resolve the background and content color for this list item in different states. See ListItemDefaults.colors

tonalElevation: Dp = ListItemDefaults.Elevation

the tonal elevation of this list item

shadowElevation: Dp = ListItemDefaults.Elevation

the shadow elevation of this list item

LoadingIndicator

@ExperimentalMaterial3ExpressiveApi
@Composable
fun LoadingIndicator(
    modifier: Modifier = Modifier,
    color: Color = LoadingIndicatorDefaults.indicatorColor,
    polygons: List<RoundedPolygon> = LoadingIndicatorDefaults.IndeterminateIndicatorPolygons
): Unit

A Material Design loading indicator.

This version of the loading indicator animates and morphs between various shapes as long as the loading indicator is visible.

Loading indicator image

It can be created like this:

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.LoadingIndicator
import androidx.compose.ui.Alignment

Column(horizontalAlignment = Alignment.CenterHorizontally) { LoadingIndicator() }
Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this loading indicator

color: Color = LoadingIndicatorDefaults.indicatorColor

the loading indicator's color

polygons: List<RoundedPolygon> = LoadingIndicatorDefaults.IndeterminateIndicatorPolygons

a list of RoundedPolygons for the sequence of shapes this loading indicator will morph between. The loading indicator expects at least two items in that list.

Throws
kotlin.IllegalArgumentException

if the polygons list holds less than two items

LoadingIndicator

@ExperimentalMaterial3ExpressiveApi
@Composable
fun LoadingIndicator(
    progress: () -> Float,
    modifier: Modifier = Modifier,
    color: Color = LoadingIndicatorDefaults.indicatorColor,
    polygons: List<RoundedPolygon> = LoadingIndicatorDefaults.DeterminateIndicatorPolygons
): Unit

A Material Design loading indicator.

This version of the loading indicator morphs between its polygons shapes by the value of its progress.

Loading indicator image

It can be created like this:

import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.spring
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.width
import androidx.compose.material3.LoadingIndicator
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

var progress by remember { mutableFloatStateOf(0f) }
val animatedProgress by
    animateFloatAsState(
        targetValue = progress,
        animationSpec =
            spring(
                dampingRatio = Spring.DampingRatioNoBouncy,
                stiffness = Spring.StiffnessVeryLow,
                visibilityThreshold = 1 / 1000f
            )
    )

Column(horizontalAlignment = Alignment.CenterHorizontally) {
    LoadingIndicator(progress = { animatedProgress })
    Spacer(Modifier.requiredHeight(30.dp))
    Text("Set loading progress:")
    Slider(
        modifier = Modifier.width(300.dp),
        value = progress,
        valueRange = 0f..1f,
        onValueChange = { progress = it },
    )
}
Parameters
progress: () -> Float

the progress of this loading indicator, where 0.0 represents no progress and 1.0 represents full progress. Values outside of this range are coerced into the range. The indicator will morph its shapes between the provided polygons according to the value of the progress.

modifier: Modifier = Modifier

the Modifier to be applied to this loading indicator

color: Color = LoadingIndicatorDefaults.indicatorColor

the loading indicator's color

polygons: List<RoundedPolygon> = LoadingIndicatorDefaults.DeterminateIndicatorPolygons

a list of RoundedPolygons for the sequence of shapes this loading indicator will morph between as it progresses from 0.0 to 1.0. The loading indicator expects at least two items in that list.

Throws
kotlin.IllegalArgumentException

if the polygons list holds less than two items

MaterialExpressiveTheme

@ExperimentalMaterial3ExpressiveApi
@Composable
fun MaterialExpressiveTheme(
    colorScheme: ColorScheme? = null,
    motionScheme: MotionScheme? = null,
    shapes: Shapes? = null,
    typography: Typography? = null,
    content: @Composable () -> Unit
): Unit

Material Expressive Theming refers to the customization of your Material Design app to better reflect your product’s brand.

Material components such as Button and Checkbox use values provided here when retrieving default values.

All values may be set by providing this component with the colorScheme, typography, shapes attributes. Use this to configure the overall theme of elements within this MaterialTheme.

Any values that are not set will fall back to the defaults. To inherit the current value from the theme, pass them into subsequent calls and override only the parts of the theme definition that need to change.

Alternatively, only call this function at the top of your application, and then call MaterialTheme to specify separate MaterialTheme(s) for different screens / parts of your UI, overriding only the parts of the theme definition that need to change.

import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Button
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialExpressiveTheme
import androidx.compose.material3.Shapes
import androidx.compose.material3.Text
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.expressiveLightColorScheme
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp

val isDarkTheme = isSystemInDarkTheme()
val supportsDynamicColor = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S

val darkColorScheme = darkColorScheme(primary = Color(0xFF66ffc7))

val colorScheme =
    when {
        supportsDynamicColor && isDarkTheme -> {
            dynamicDarkColorScheme(LocalContext.current)
        }
        supportsDynamicColor && !isDarkTheme -> {
            dynamicLightColorScheme(LocalContext.current)
        }
        isDarkTheme -> darkColorScheme
        else -> expressiveLightColorScheme()
    }

val shapes = Shapes(largeIncreased = RoundedCornerShape(36.0.dp))

MaterialExpressiveTheme(colorScheme = colorScheme, shapes = shapes) {
    val currentTheme = if (!isSystemInDarkTheme()) "light" else "dark"
    ExtendedFloatingActionButton(
        text = { Text("FAB with text style and color from $currentTheme expressive theme") },
        icon = { Icon(Icons.Filled.Favorite, contentDescription = "Localized Description") },
        onClick = {}
    )
}
Parameters
colorScheme: ColorScheme? = null

A complete definition of the Material Color theme for this hierarchy

motionScheme: MotionScheme? = null

A complete definition of the Material motion theme for this hierarchy

shapes: Shapes? = null

A set of corner shapes to be used as this hierarchy's shape system

typography: Typography? = null

A set of text styles to be used as this hierarchy's typography system

content: @Composable () -> Unit

The content inheriting this theme

MaterialTheme

@Composable
fun MaterialTheme(
    colorScheme: ColorScheme = MaterialTheme.colorScheme,
    shapes: Shapes = MaterialTheme.shapes,
    typography: Typography = MaterialTheme.typography,
    content: @Composable () -> Unit
): Unit

Material Theming refers to the customization of your Material Design app to better reflect your product’s brand.

Material components such as Button and Checkbox use values provided here when retrieving default values.

All values may be set by providing this component with the colorScheme, typography and shapes attributes. Use this to configure the overall theme of elements within this MaterialTheme.

Any values that are not set will inherit the current value from the theme, falling back to the defaults if there is no parent MaterialTheme. This allows using a MaterialTheme at the top of your application, and then separate MaterialTheme(s) for different screens / parts of your UI, overriding only the parts of the theme definition that need to change.

import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Button
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Shapes
import androidx.compose.material3.Text
import androidx.compose.material3.Typography
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

val isDarkTheme = isSystemInDarkTheme()
val supportsDynamicColor = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S

val lightColorScheme = lightColorScheme(primary = Color(0xFF1EB980))

val darkColorScheme = darkColorScheme(primary = Color(0xFF66ffc7))

val colorScheme =
    when {
        supportsDynamicColor && isDarkTheme -> {
            dynamicDarkColorScheme(LocalContext.current)
        }
        supportsDynamicColor && !isDarkTheme -> {
            dynamicLightColorScheme(LocalContext.current)
        }
        isDarkTheme -> darkColorScheme
        else -> lightColorScheme
    }

val typography =
    Typography(
        displaySmall = TextStyle(fontWeight = FontWeight.W100, fontSize = 96.sp),
        labelLarge = TextStyle(fontWeight = FontWeight.W600, fontSize = 14.sp)
    )

val shapes = Shapes(extraSmall = RoundedCornerShape(3.0.dp), small = RoundedCornerShape(6.0.dp))

MaterialTheme(colorScheme = colorScheme, typography = typography, shapes = shapes) {
    val currentTheme = if (!isSystemInDarkTheme()) "light" else "dark"
    ExtendedFloatingActionButton(
        text = { Text("FAB with text style and color from $currentTheme theme") },
        icon = { Icon(Icons.Filled.Favorite, contentDescription = "Localized Description") },
        onClick = {}
    )
}
Parameters
colorScheme: ColorScheme = MaterialTheme.colorScheme

A complete definition of the Material Color theme for this hierarchy

shapes: Shapes = MaterialTheme.shapes

A set of corner shapes to be used as this hierarchy's shape system

typography: Typography = MaterialTheme.typography

A set of text styles to be used as this hierarchy's typography system

content: @Composable () -> Unit

The content inheriting this theme

MaterialTheme

@ExperimentalMaterial3ExpressiveApi
@Composable
fun MaterialTheme(
    colorScheme: ColorScheme = MaterialTheme.colorScheme,
    motionScheme: MotionScheme = MaterialTheme.motionScheme,
    shapes: Shapes = MaterialTheme.shapes,
    typography: Typography = MaterialTheme.typography,
    content: @Composable () -> Unit
): Unit

Material Theming refers to the customization of your Material Design app to better reflect your product’s brand.

Material components such as Button and Checkbox use values provided here when retrieving default values.

All values may be set by providing this component with the colorScheme, typography attributes. Use this to configure the overall theme of elements within this MaterialTheme.

Any values that are not set will inherit the current value from the theme, falling back to the defaults if there is no parent MaterialTheme. This allows using a MaterialTheme at the top of your application, and then separate MaterialTheme(s) for different screens / parts of your UI, overriding only the parts of the theme definition that need to change.

Parameters
colorScheme: ColorScheme = MaterialTheme.colorScheme

A complete definition of the Material Color theme for this hierarchy

motionScheme: MotionScheme = MaterialTheme.motionScheme

A complete definition of the Material Motion scheme for this hierarchy

shapes: Shapes = MaterialTheme.shapes

A set of corner shapes to be used as this hierarchy's shape system

typography: Typography = MaterialTheme.typography

A set of text styles to be used as this hierarchy's typography system

MediumExtendedFloatingActionButton

@ExperimentalMaterial3ExpressiveApi
@Composable
fun MediumExtendedFloatingActionButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    shape: Shape = FloatingActionButtonDefaults.mediumExtendedFabShape,
    containerColor: Color = FloatingActionButtonDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable RowScope.() -> Unit
): Unit

Material Design medium extended floating action button.

Extended FABs help people take primary actions. They're wider than FABs to accommodate a text label and larger target area.

The other medium extended floating action button overload supports a text label and icon.

import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.MediumExtendedFloatingActionButton
import androidx.compose.material3.Text

MediumExtendedFloatingActionButton(onClick = { /* do something */ }) {
    Text(text = "Medium Extended FAB")
}
Parameters
onClick: () -> Unit

called when this FAB is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this FAB

shape: Shape = FloatingActionButtonDefaults.mediumExtendedFabShape

defines the shape of this FAB's container and shadow (when using elevation)

containerColor: Color = FloatingActionButtonDefaults.containerColor

the color used for the background of this FAB. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this FAB. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation()

FloatingActionButtonElevation used to resolve the elevation for this FAB in different states. This controls the size of the shadow below the FAB. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See also: Surface.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this FAB. You can use this to change the FAB's appearance or preview the FAB in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable RowScope.() -> Unit

the content of this FAB, typically a Text label

MediumExtendedFloatingActionButton

@ExperimentalMaterial3ExpressiveApi
@Composable
fun MediumExtendedFloatingActionButton(
    text: @Composable () -> Unit,
    icon: @Composable () -> Unit,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    expanded: Boolean = true,
    shape: Shape = FloatingActionButtonDefaults.mediumExtendedFabShape,
    containerColor: Color = FloatingActionButtonDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design medium extended floating action button.

Extended FABs help people take primary actions. They're wider than FABs to accommodate a text label and larger target area.

The other medium extended floating action button overload is for FABs without an icon.

Default content description for accessibility is extended from the extended fabs icon. For custom behavior, you can provide your own via Modifier.semantics.

import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MediumExtendedFloatingActionButton
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier

MediumExtendedFloatingActionButton(
    onClick = { /* do something */ },
    icon = {
        Icon(
            Icons.Filled.Add,
            "Localized description",
            modifier = Modifier.size(FloatingActionButtonDefaults.MediumIconSize)
        )
    },
    text = { Text(text = "Medium Extended FAB") },
)
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FabPosition
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MediumExtendedFloatingActionButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val listState = rememberLazyListState()
// The FAB is initially expanded. Once the first visible item is past the first item we
// collapse the FAB. We use a remembered derived state to minimize unnecessary compositions.
val expandedFab by remember { derivedStateOf { listState.firstVisibleItemIndex == 0 } }
Scaffold(
    floatingActionButton = {
        MediumExtendedFloatingActionButton(
            onClick = { /* do something */ },
            expanded = expandedFab,
            icon = {
                Icon(
                    Icons.Filled.Add,
                    "Localized Description",
                    modifier = Modifier.size(FloatingActionButtonDefaults.MediumIconSize)
                )
            },
            text = { Text(text = "Medium Extended FAB") },
        )
    },
    floatingActionButtonPosition = FabPosition.End,
) {
    LazyColumn(state = listState, modifier = Modifier.fillMaxSize()) {
        for (index in 0 until 100) {
            item { Text(text = "List item - $index", modifier = Modifier.padding(24.dp)) }
        }
    }
}
Parameters
text: @Composable () -> Unit

label displayed inside this FAB

icon: @Composable () -> Unit

icon for this FAB, typically an Icon

onClick: () -> Unit

called when this FAB is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this FAB

expanded: Boolean = true

controls the expansion state of this FAB. In an expanded state, the FAB will show both the icon and text. In a collapsed state, the FAB will show only the icon.

shape: Shape = FloatingActionButtonDefaults.mediumExtendedFabShape

defines the shape of this FAB's container and shadow (when using elevation)

containerColor: Color = FloatingActionButtonDefaults.containerColor

the color used for the background of this FAB. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this FAB. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation()

FloatingActionButtonElevation used to resolve the elevation for this FAB in different states. This controls the size of the shadow below the FAB. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See also: Surface.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this FAB. You can use this to change the FAB's appearance or preview the FAB in different states. Note that if null is provided, interactions will still happen internally.

MediumFloatingActionButton

@ExperimentalMaterial3ExpressiveApi
@Composable
fun MediumFloatingActionButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    shape: Shape = FloatingActionButtonDefaults.mediumShape,
    containerColor: Color = FloatingActionButtonDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable () -> Unit
): Unit

Material Design medium floating action button.

The FAB represents the most important action on a screen. It puts key actions within reach.

import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MediumFloatingActionButton
import androidx.compose.ui.Modifier

MediumFloatingActionButton(
    onClick = { /* do something */ },
) {
    Icon(
        Icons.Filled.Add,
        contentDescription = "Localized description",
        modifier = Modifier.size(FloatingActionButtonDefaults.MediumIconSize),
    )
}

FABs can also be shown and hidden with an animation when the main content is scrolled:

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FabPosition
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MediumFloatingActionButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.animateFloatingActionButton
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val listState = rememberLazyListState()
// The FAB is initially shown. Upon scrolling past the first item we hide the FAB by using a
// remembered derived state to minimize unnecessary compositions.
val fabVisible by remember { derivedStateOf { listState.firstVisibleItemIndex == 0 } }

Scaffold(
    floatingActionButton = {
        MediumFloatingActionButton(
            modifier =
                Modifier.animateFloatingActionButton(
                    visible = fabVisible,
                    alignment = Alignment.BottomEnd
                ),
            onClick = { /* do something */ },
        ) {
            Icon(
                Icons.Filled.Add,
                contentDescription = "Localized description",
                modifier = Modifier.size(FloatingActionButtonDefaults.MediumIconSize),
            )
        }
    },
    floatingActionButtonPosition = FabPosition.End,
) {
    LazyColumn(state = listState, modifier = Modifier.fillMaxSize()) {
        for (index in 0 until 100) {
            item { Text(text = "List item - $index", modifier = Modifier.padding(24.dp)) }
        }
    }
}
Parameters
onClick: () -> Unit

called when this FAB is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this FAB

shape: Shape = FloatingActionButtonDefaults.mediumShape

defines the shape of this FAB's container and shadow (when using elevation)

containerColor: Color = FloatingActionButtonDefaults.containerColor

the color used for the background of this FAB. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this FAB. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation()

FloatingActionButtonElevation used to resolve the elevation for this FAB in different states. This controls the size of the shadow below the FAB. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See also: Surface.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this FAB. You can use this to change the FAB's appearance or preview the FAB in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable () -> Unit

the content of this FAB, typically an Icon

MediumTopAppBar

@ExperimentalMaterial3Api
@Composable
fun MediumTopAppBar(
    title: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    navigationIcon: @Composable () -> Unit = {},
    actions: @Composable RowScope.() -> Unit = {},
    collapsedHeight: Dp = TopAppBarDefaults.MediumAppBarCollapsedHeight,
    expandedHeight: Dp = TopAppBarDefaults.MediumAppBarExpandedHeight,
    windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
    colors: TopAppBarColors = TopAppBarDefaults.mediumTopAppBarColors(),
    scrollBehavior: TopAppBarScrollBehavior? = null
): Unit

Material Design medium top app bar.

Top app bars display information and actions at the top of a screen.

Medium top app bar image

This MediumTopAppBar has slots for a title, navigation icon, and actions. In its default expanded state, the title is displayed in a second row under the navigation and actions.

A medium top app bar that uses a scrollBehavior to customize its nested scrolling behavior when working in conjunction with scrolling content looks like:

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MediumTopAppBar
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp

val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    topBar = {
        MediumTopAppBar(
            title = {
                Text("Medium TopAppBar", maxLines = 1, overflow = TextOverflow.Ellipsis)
            },
            navigationIcon = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Menu,
                        contentDescription = "Localized description"
                    )
                }
            },
            actions = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Favorite,
                        contentDescription = "Localized description"
                    )
                }
            },
            scrollBehavior = scrollBehavior
        )
    },
    content = { innerPadding ->
        LazyColumn(
            contentPadding = innerPadding,
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            val list = (0..75).map { it.toString() }
            items(count = list.size) {
                Text(
                    text = list[it],
                    style = MaterialTheme.typography.bodyLarge,
                    modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                )
            }
        }
    }
)
Parameters
title: @Composable () -> Unit

the title to be displayed in the top app bar. This title will be used in the app bar's expanded and collapsed states, although in its collapsed state it will be composed with a smaller sized TextStyle

modifier: Modifier = Modifier

the Modifier to be applied to this top app bar

navigationIcon: @Composable () -> Unit = {}

the navigation icon displayed at the start of the top app bar. This should typically be an IconButton or IconToggleButton.

actions: @Composable RowScope.() -> Unit = {}

the actions displayed at the end of the top app bar. This should typically be IconButtons. The default layout here is a Row, so icons inside will be placed horizontally.

collapsedHeight: Dp = TopAppBarDefaults.MediumAppBarCollapsedHeight

this app bar height when collapsed by a provided scrollBehavior. This value must be specified and finite, otherwise it will be ignored and replaced with TopAppBarDefaults.MediumAppBarCollapsedHeight.

expandedHeight: Dp = TopAppBarDefaults.MediumAppBarExpandedHeight

this app bar's maximum height. When a specified scrollBehavior causes the app bar to collapse or expand, this value will represent the maximum height that the app-bar will be allowed to expand. The expanded height is expected to be greater or equal to the collapsedHeight, and the function will throw an IllegalArgumentException otherwise. Also, this value must be specified and finite, otherwise it will be ignored and replaced with TopAppBarDefaults.MediumAppBarExpandedHeight.

windowInsets: WindowInsets = TopAppBarDefaults.windowInsets

a window insets that app bar will respect.

colors: TopAppBarColors = TopAppBarDefaults.mediumTopAppBarColors()

TopAppBarColors that will be used to resolve the colors used for this top app bar in different states. See TopAppBarDefaults.mediumTopAppBarColors.

scrollBehavior: TopAppBarScrollBehavior? = null

a TopAppBarScrollBehavior which holds various offset values that will be applied by this top app bar to set up its height and colors. A scroll behavior is designed to work in conjunction with a scrolled content to change the top app bar appearance as the content scrolls. See TopAppBarScrollBehavior.nestedScrollConnection.

Throws
kotlin.IllegalArgumentException

if the provided expandedHeight is smaller than the collapsedHeight

MediumTopAppBar

@ExperimentalMaterial3ExpressiveApi
@Composable
fun MediumTopAppBar(
    title: @Composable () -> Unit,
    subtitle: (@Composable () -> Unit)?,
    modifier: Modifier = Modifier,
    navigationIcon: @Composable () -> Unit = {},
    actions: @Composable RowScope.() -> Unit = {},
    titleHorizontalAlignment: TopAppBarTitleAlignment = TopAppBarTitleAlignment.Start,
    collapsedHeight: Dp = TopAppBarDefaults.MediumAppBarCollapsedHeight,
    expandedHeight: Dp = if (subtitle != null) { TopAppBarDefaults.MediumAppBarWithSubtitleExpandedHeight } else { TopAppBarDefaults.MediumAppBarWithoutSubtitleExpandedHeight },
    windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
    colors: TopAppBarColors = TopAppBarDefaults.mediumTopAppBarColors(),
    scrollBehavior: TopAppBarScrollBehavior? = null
): Unit

Material Design medium top app bar.

Top app bars display information and actions at the top of a screen.

Medium top app bar image

This MediumTopAppBar has slots for a title, subtitle, navigation icon, and actions. In its default expanded state, the title and subtitle are displayed in a second row under the navigation and actions.

A medium top app bar that uses a scrollBehavior to customize its nested scrolling behavior when working in conjunction with scrolling content looks like:

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MediumTopAppBar
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarTitleAlignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp

val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    topBar = {
        MediumTopAppBar(
            title = {
                Text("Medium TopAppBar", maxLines = 1, overflow = TextOverflow.Ellipsis)
            },
            subtitle = { Text("Subtitle", maxLines = 1, overflow = TextOverflow.Ellipsis) },
            titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
            navigationIcon = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Menu,
                        contentDescription = "Localized description"
                    )
                }
            },
            actions = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Favorite,
                        contentDescription = "Localized description"
                    )
                }
            },
            scrollBehavior = scrollBehavior
        )
    },
    content = { innerPadding ->
        LazyColumn(
            contentPadding = innerPadding,
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            val list = (0..75).map { it.toString() }
            items(count = list.size) {
                Text(
                    text = list[it],
                    style = MaterialTheme.typography.bodyLarge,
                    modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                )
            }
        }
    }
)
Parameters
title: @Composable () -> Unit

the title to be displayed in the top app bar. This title will be used in the app bar's expanded and collapsed states, although in its collapsed state it will be composed with a smaller sized TextStyle

subtitle: (@Composable () -> Unit)?

the subtitle to be displayed in the top app bar. This subtitle will be used in the app bar's expanded and collapsed states

modifier: Modifier = Modifier

the Modifier to be applied to this top app bar

navigationIcon: @Composable () -> Unit = {}

the navigation icon displayed at the start of the top app bar. This should typically be an IconButton or IconToggleButton.

actions: @Composable RowScope.() -> Unit = {}

the actions displayed at the end of the top app bar. This should typically be IconButtons. The default layout here is a Row, so icons inside will be placed horizontally.

titleHorizontalAlignment: TopAppBarTitleAlignment = TopAppBarTitleAlignment.Start

the horizontal alignment of the title and subtitle

collapsedHeight: Dp = TopAppBarDefaults.MediumAppBarCollapsedHeight

this app bar height when collapsed by a provided scrollBehavior. This value must be specified and finite, otherwise it will be ignored and replaced with TopAppBarDefaults.MediumAppBarCollapsedHeight.

expandedHeight: Dp = if (subtitle != null) { TopAppBarDefaults.MediumAppBarWithSubtitleExpandedHeight } else { TopAppBarDefaults.MediumAppBarWithoutSubtitleExpandedHeight }

this app bar's maximum height. When a specified scrollBehavior causes the app bar to collapse or expand, this value will represent the maximum height that the app-bar will be allowed to expand. The expanded height is expected to be greater or equal to the collapsedHeight, and the function will throw an IllegalArgumentException otherwise. Also, this value must be specified and finite, otherwise it will be ignored and replaced with TopAppBarDefaults.MediumAppBarExpandedHeight.

windowInsets: WindowInsets = TopAppBarDefaults.windowInsets

a window insets that app bar will respect.

colors: TopAppBarColors = TopAppBarDefaults.mediumTopAppBarColors()

TopAppBarColors that will be used to resolve the colors used for this top app bar in different states. See TopAppBarDefaults.mediumTopAppBarColors.

scrollBehavior: TopAppBarScrollBehavior? = null

a TopAppBarScrollBehavior which holds various offset values that will be applied by this top app bar to set up its height and colors. A scroll behavior is designed to work in conjunction with a scrolled content to change the top app bar appearance as the content scrolls. See TopAppBarScrollBehavior.nestedScrollConnection.

Throws
kotlin.IllegalArgumentException

if the provided expandedHeight is smaller than the collapsedHeight

ModalBottomSheet

@Composable
@ExperimentalMaterial3Api
fun ModalBottomSheet(
    onDismissRequest: () -> Unit,
    modifier: Modifier = Modifier,
    sheetState: SheetState = rememberModalBottomSheetState(),
    sheetMaxWidth: Dp = BottomSheetDefaults.SheetMaxWidth,
    sheetGesturesEnabled: Boolean = true,
    shape: Shape = BottomSheetDefaults.ExpandedShape,
    containerColor: Color = BottomSheetDefaults.ContainerColor,
    contentColor: Color = contentColorFor(containerColor),
    tonalElevation: Dp = 0.dp,
    scrimColor: Color = BottomSheetDefaults.ScrimColor,
    dragHandle: (@Composable () -> Unit)? = { BottomSheetDefaults.DragHandle() },
    contentWindowInsets: @Composable () -> WindowInsets = { BottomSheetDefaults.windowInsets },
    properties: ModalBottomSheetProperties = ModalBottomSheetProperties( isAppearanceLightStatusBars = contentColor.isDark(), isAppearanceLightNavigationBars = contentColor.isDark() ),
    content: @Composable ColumnScope.() -> Unit
): Unit

Material Design modal bottom sheet.

Modal bottom sheets are used as an alternative to inline menus or simple dialogs on mobile, especially when offering a long list of action items, or when items require longer descriptions and icons. Like dialogs, modal bottom sheets appear in front of app content, disabling all other app functionality when they appear, and remaining on screen until confirmed, dismissed, or a required action has been taken.

Bottom sheet image

A simple example of a modal bottom sheet looks like this:

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.selection.toggleable
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Button
import androidx.compose.material3.Checkbox
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.ListItemDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.dp

var openBottomSheet by rememberSaveable { mutableStateOf(false) }
var skipPartiallyExpanded by rememberSaveable { mutableStateOf(false) }
val scope = rememberCoroutineScope()
val bottomSheetState =
    rememberModalBottomSheetState(skipPartiallyExpanded = skipPartiallyExpanded)

// App content
Column(
    horizontalAlignment = Alignment.Start,
    verticalArrangement = Arrangement.spacedBy(4.dp)
) {
    Row(
        Modifier.toggleable(
            value = skipPartiallyExpanded,
            role = Role.Checkbox,
            onValueChange = { checked -> skipPartiallyExpanded = checked }
        )
    ) {
        Checkbox(checked = skipPartiallyExpanded, onCheckedChange = null)
        Spacer(Modifier.width(16.dp))
        Text("Skip partially expanded State")
    }
    Button(
        onClick = { openBottomSheet = !openBottomSheet },
        modifier = Modifier.align(Alignment.CenterHorizontally)
    ) {
        Text(text = "Show Bottom Sheet")
    }
}

// Sheet content
if (openBottomSheet) {

    ModalBottomSheet(
        onDismissRequest = { openBottomSheet = false },
        sheetState = bottomSheetState,
    ) {
        Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
            Button(
                // Note: If you provide logic outside of onDismissRequest to remove the sheet,
                // you must additionally handle intended state cleanup, if any.
                onClick = {
                    scope
                        .launch { bottomSheetState.hide() }
                        .invokeOnCompletion {
                            if (!bottomSheetState.isVisible) {
                                openBottomSheet = false
                            }
                        }
                }
            ) {
                Text("Hide Bottom Sheet")
            }
        }
        var text by remember { mutableStateOf("") }
        OutlinedTextField(
            value = text,
            onValueChange = { text = it },
            modifier = Modifier.padding(horizontal = 16.dp),
            label = { Text("Text field") }
        )
        LazyColumn {
            items(25) {
                ListItem(
                    headlineContent = { Text("Item $it") },
                    leadingContent = {
                        Icon(
                            Icons.Default.Favorite,
                            contentDescription = "Localized description"
                        )
                    },
                    colors =
                        ListItemDefaults.colors(
                            containerColor = MaterialTheme.colorScheme.surfaceContainerLow
                        ),
                )
            }
        }
    }
}
Parameters
onDismissRequest: () -> Unit

Executes when the user clicks outside of the bottom sheet, after sheet animates to Hidden.

modifier: Modifier = Modifier

Optional Modifier for the bottom sheet.

sheetState: SheetState = rememberModalBottomSheetState()

The state of the bottom sheet.

sheetMaxWidth: Dp = BottomSheetDefaults.SheetMaxWidth

Dp that defines what the maximum width the sheet will take. Pass in Dp.Unspecified for a sheet that spans the entire screen width.

sheetGesturesEnabled: Boolean = true

Whether the bottom sheet can be interacted with by gestures.

shape: Shape = BottomSheetDefaults.ExpandedShape

The shape of the bottom sheet.

containerColor: Color = BottomSheetDefaults.ContainerColor

The color used for the background of this bottom sheet

contentColor: Color = contentColorFor(containerColor)

The preferred color for content inside this bottom sheet. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

tonalElevation: Dp = 0.dp

when containerColor is ColorScheme.surface, a translucent primary color overlay is applied on top of the container. A higher tonal elevation value will result in a darker color in light theme and lighter color in dark theme. See also: Surface.

scrimColor: Color = BottomSheetDefaults.ScrimColor

Color of the scrim that obscures content when the bottom sheet is open.

dragHandle: (@Composable () -> Unit)? = { BottomSheetDefaults.DragHandle() }

Optional visual marker to swipe the bottom sheet.

contentWindowInsets: @Composable () -> WindowInsets = { BottomSheetDefaults.windowInsets }

window insets to be passed to the bottom sheet content via PaddingValues params.

properties: ModalBottomSheetProperties = ModalBottomSheetProperties( isAppearanceLightStatusBars = contentColor.isDark(), isAppearanceLightNavigationBars = contentColor.isDark() )

ModalBottomSheetProperties for further customization of this modal bottom sheet's window behavior.

content: @Composable ColumnScope.() -> Unit

The content to be displayed inside the bottom sheet.

ModalDrawerSheet

@Composable
fun ModalDrawerSheet(
    modifier: Modifier = Modifier,
    drawerShape: Shape = DrawerDefaults.shape,
    drawerContainerColor: Color = DrawerDefaults.modalContainerColor,
    drawerContentColor: Color = contentColorFor(drawerContainerColor),
    drawerTonalElevation: Dp = DrawerDefaults.ModalDrawerElevation,
    windowInsets: WindowInsets = DrawerDefaults.windowInsets,
    content: @Composable ColumnScope.() -> Unit
): Unit

Content inside of a modal navigation drawer.

Note: This version of ModalDrawerSheet does not handle back by default. For automatic back handling and predictive back animations on Android 14+, use the ModalDrawerSheet that accepts drawerState as a param.

Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this drawer's content

drawerShape: Shape = DrawerDefaults.shape

defines the shape of this drawer's container

drawerContainerColor: Color = DrawerDefaults.modalContainerColor

the color used for the background of this drawer. Use Color.Transparent to have no color.

drawerContentColor: Color = contentColorFor(drawerContainerColor)

the preferred color for content inside this drawer. Defaults to either the matching content color for drawerContainerColor, or to the current LocalContentColor if drawerContainerColor is not a color from the theme.

drawerTonalElevation: Dp = DrawerDefaults.ModalDrawerElevation

when drawerContainerColor is ColorScheme.surface, a translucent primary color overlay is applied on top of the container. A higher tonal elevation value will result in a darker color in light theme and lighter color in dark theme. See also: Surface.

windowInsets: WindowInsets = DrawerDefaults.windowInsets

a window insets for the sheet.

content: @Composable ColumnScope.() -> Unit

content inside of a modal navigation drawer

ModalDrawerSheet

@Composable
fun ModalDrawerSheet(
    drawerState: DrawerState,
    modifier: Modifier = Modifier,
    drawerShape: Shape = DrawerDefaults.shape,
    drawerContainerColor: Color = DrawerDefaults.modalContainerColor,
    drawerContentColor: Color = contentColorFor(drawerContainerColor),
    drawerTonalElevation: Dp = DrawerDefaults.ModalDrawerElevation,
    windowInsets: WindowInsets = DrawerDefaults.windowInsets,
    content: @Composable ColumnScope.() -> Unit
): Unit

Content inside of a modal navigation drawer.

Note: This version of ModalDrawerSheet requires a drawerState to be provided and will handle back by default for all Android versions, as well as animate during predictive back on Android 14+.

Parameters
drawerState: DrawerState

state of the drawer

modifier: Modifier = Modifier

the Modifier to be applied to this drawer's content

drawerShape: Shape = DrawerDefaults.shape

defines the shape of this drawer's container

drawerContainerColor: Color = DrawerDefaults.modalContainerColor

the color used for the background of this drawer. Use Color.Transparent to have no color.

drawerContentColor: Color = contentColorFor(drawerContainerColor)

the preferred color for content inside this drawer. Defaults to either the matching content color for drawerContainerColor, or to the current LocalContentColor if drawerContainerColor is not a color from the theme.

drawerTonalElevation: Dp = DrawerDefaults.ModalDrawerElevation

when drawerContainerColor is ColorScheme.surface, a translucent primary color overlay is applied on top of the container. A higher tonal elevation value will result in a darker color in light theme and lighter color in dark theme. See also: Surface.

windowInsets: WindowInsets = DrawerDefaults.windowInsets

a window insets for the sheet.

content: @Composable ColumnScope.() -> Unit

content inside of a modal navigation drawer

ModalNavigationDrawer

@Composable
fun ModalNavigationDrawer(
    drawerContent: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    drawerState: DrawerState = rememberDrawerState(DrawerValue.Closed),
    gesturesEnabled: Boolean = true,
    scrimColor: Color = DrawerDefaults.scrimColor,
    content: @Composable () -> Unit
): Unit

Material Design navigation drawer.

Navigation drawers provide ergonomic access to destinations in an app.

Modal navigation drawers block interaction with the rest of an app’s content with a scrim. They are elevated above most of the app’s UI and don’t affect the screen’s layout grid.

Navigation drawer image

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material.icons.filled.Bookmarks
import androidx.compose.material.icons.filled.CalendarMonth
import androidx.compose.material.icons.filled.Dashboard
import androidx.compose.material.icons.filled.Email
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Group
import androidx.compose.material.icons.filled.Headphones
import androidx.compose.material.icons.filled.Image
import androidx.compose.material.icons.filled.JoinFull
import androidx.compose.material.icons.filled.Keyboard
import androidx.compose.material.icons.filled.Laptop
import androidx.compose.material.icons.filled.Map
import androidx.compose.material.icons.filled.Navigation
import androidx.compose.material.icons.filled.Outbox
import androidx.compose.material.icons.filled.PushPin
import androidx.compose.material.icons.filled.QrCode
import androidx.compose.material.icons.filled.Radio
import androidx.compose.material3.Button
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.Icon
import androidx.compose.material3.ModalDrawerSheet
import androidx.compose.material3.ModalNavigationDrawer
import androidx.compose.material3.NavigationDrawerItem
import androidx.compose.material3.NavigationDrawerItemDefaults
import androidx.compose.material3.Text
import androidx.compose.material3.rememberDrawerState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val drawerState = rememberDrawerState(DrawerValue.Closed)
val scope = rememberCoroutineScope()
// icons to mimic drawer destinations
val items =
    listOf(
        Icons.Default.AccountCircle,
        Icons.Default.Bookmarks,
        Icons.Default.CalendarMonth,
        Icons.Default.Dashboard,
        Icons.Default.Email,
        Icons.Default.Favorite,
        Icons.Default.Group,
        Icons.Default.Headphones,
        Icons.Default.Image,
        Icons.Default.JoinFull,
        Icons.Default.Keyboard,
        Icons.Default.Laptop,
        Icons.Default.Map,
        Icons.Default.Navigation,
        Icons.Default.Outbox,
        Icons.Default.PushPin,
        Icons.Default.QrCode,
        Icons.Default.Radio,
    )
val selectedItem = remember { mutableStateOf(items[0]) }
ModalNavigationDrawer(
    drawerState = drawerState,
    drawerContent = {
        ModalDrawerSheet(drawerState) {
            Column(Modifier.verticalScroll(rememberScrollState())) {
                Spacer(Modifier.height(12.dp))
                items.forEach { item ->
                    NavigationDrawerItem(
                        icon = { Icon(item, contentDescription = null) },
                        label = { Text(item.name.substringAfterLast(".")) },
                        selected = item == selectedItem.value,
                        onClick = {
                            scope.launch { drawerState.close() }
                            selectedItem.value = item
                        },
                        modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
                    )
                }
            }
        }
    },
    content = {
        Column(
            modifier = Modifier.fillMaxSize().padding(16.dp),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text(text = if (drawerState.isClosed) ">>> Swipe >>>" else "<<< Swipe <<<")
            Spacer(Modifier.height(20.dp))
            Button(onClick = { scope.launch { drawerState.open() } }) { Text("Click to open") }
        }
    }
)
Parameters
drawerContent: @Composable () -> Unit

content inside this drawer

modifier: Modifier = Modifier

the Modifier to be applied to this drawer

drawerState: DrawerState = rememberDrawerState(DrawerValue.Closed)

state of the drawer

gesturesEnabled: Boolean = true

whether or not the drawer can be interacted by gestures

scrimColor: Color = DrawerDefaults.scrimColor

color of the scrim that obscures content when the drawer is open

content: @Composable () -> Unit

content of the rest of the UI

ModalWideNavigationRail

@ExperimentalMaterial3ExpressiveApi
@Composable
fun ModalWideNavigationRail(
    modifier: Modifier = Modifier,
    state: WideNavigationRailState = rememberWideNavigationRailState(),
    hideOnCollapse: Boolean = false,
    collapsedShape: Shape = WideNavigationRailDefaults.containerShape,
    expandedShape: Shape = WideNavigationRailDefaults.modalContainerShape,
    colors: WideNavigationRailColors = WideNavigationRailDefaults.colors(),
    header: (@Composable () -> Unit)? = null,
    expandedHeaderTopPadding: Dp = 0.dp,
    windowInsets: WindowInsets = WideNavigationRailDefaults.windowInsets,
    arrangement: WideNavigationRailArrangement = WideNavigationRailDefaults.Arrangement,
    expandedProperties: ModalWideNavigationRailProperties = ModalWideNavigationRailDefaults.Properties,
    content: @Composable () -> Unit
): Unit

Material design modal wide navigation rail.

Wide navigation rails provide access to primary destinations in apps when using tablet and desktop screens.

The modal wide navigation rail should be used to display multiple WideNavigationRailItems, each representing a singular app destination, and, optionally, a header containing a menu button, a FloatingActionButton, and/or a logo. Each destination is typically represented by an icon and a text label.

The ModalWideNavigationRail when collapsed behaves like a collapsed WideNavigationRail. When expanded, the modal wide navigation rail blocks interaction with the rest of an app’s content with a scrim. It is elevated above the app’s UI and doesn't affect the screen’s layout grid. That can be achieved like so:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.MenuOpen
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.icons.filled.Star
import androidx.compose.material.icons.outlined.FavoriteBorder
import androidx.compose.material.icons.outlined.Home
import androidx.compose.material.icons.outlined.StarBorder
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ModalWideNavigationRail
import androidx.compose.material3.NavigationRail
import androidx.compose.material3.NavigationRailItem
import androidx.compose.material3.Text
import androidx.compose.material3.WideNavigationRail
import androidx.compose.material3.WideNavigationRailItem
import androidx.compose.material3.WideNavigationRailValue
import androidx.compose.material3.rememberWideNavigationRailState
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.stateDescription
import androidx.compose.ui.unit.dp

var selectedItem by remember { mutableIntStateOf(0) }
val items = listOf("Home", "Search", "Settings")
val selectedIcons = listOf(Icons.Filled.Home, Icons.Filled.Favorite, Icons.Filled.Star)
val unselectedIcons =
    listOf(Icons.Outlined.Home, Icons.Outlined.FavoriteBorder, Icons.Outlined.StarBorder)
val state = rememberWideNavigationRailState()
val scope = rememberCoroutineScope()

Row(Modifier.fillMaxWidth()) {
    ModalWideNavigationRail(
        state = state,
        // Note: the value of expandedHeaderTopPadding depends on the layout of your screen in
        // order to achieve the best alignment.
        expandedHeaderTopPadding = 64.dp,
        header = {
            IconButton(
                modifier =
                    Modifier.padding(start = 24.dp).semantics {
                        // The button must announce the expanded or collapsed state of the rail
                        // for accessibility.
                        stateDescription =
                            if (state.currentValue == WideNavigationRailValue.Expanded) {
                                "Expanded"
                            } else {
                                "Collapsed"
                            }
                    },
                onClick = {
                    scope.launch {
                        if (state.targetValue == WideNavigationRailValue.Expanded)
                            state.collapse()
                        else state.expand()
                    }
                }
            ) {
                if (state.targetValue == WideNavigationRailValue.Expanded) {
                    Icon(Icons.AutoMirrored.Filled.MenuOpen, "Collapse rail")
                } else {
                    Icon(Icons.Filled.Menu, "Expand rail")
                }
            }
        }
    ) {
        items.forEachIndexed { index, item ->
            WideNavigationRailItem(
                railExpanded = state.targetValue == WideNavigationRailValue.Expanded,
                icon = {
                    Icon(
                        if (selectedItem == index) selectedIcons[index]
                        else unselectedIcons[index],
                        contentDescription = item
                    )
                },
                label = { Text(item) },
                selected = selectedItem == index,
                onClick = { selectedItem = index }
            )
        }
    }

    val textString =
        if (state.currentValue == WideNavigationRailValue.Expanded) {
            "Expanded"
        } else {
            "Collapsed"
        }
    Column {
        Text(modifier = Modifier.padding(16.dp), text = "The rail is $textString.")
        Text(
            modifier = Modifier.padding(16.dp),
            text =
                "Note: The orientation of this demo has been locked to portrait mode, because" +
                    " landscape mode may result in a compact height in certain devices. For" +
                    " any compact screen dimensions, use a Navigation Bar instead."
        )
    }

    // Lock the orientation for this demo as the navigation rail may look cut off in landscape
    // in smaller screens.
    val context = LocalContext.current
    DisposableEffect(context) {
        (context as? Activity)?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
        onDispose {
            (context as? Activity)?.requestedOrientation =
                ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
        }
    }
}

For a dismissible ModalWideNavigationRail, that enters from offscreen instead of expanding from the collapsed rail, set hideOnCollapse to true. That can be achieved like so:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Star
import androidx.compose.material.icons.outlined.FavoriteBorder
import androidx.compose.material.icons.outlined.Home
import androidx.compose.material.icons.outlined.StarBorder
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.ModalWideNavigationRail
import androidx.compose.material3.NavigationRail
import androidx.compose.material3.NavigationRailItem
import androidx.compose.material3.Text
import androidx.compose.material3.WideNavigationRail
import androidx.compose.material3.WideNavigationRailItem
import androidx.compose.material3.rememberWideNavigationRailState
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp

var selectedItem by remember { mutableIntStateOf(0) }
val items = listOf("Home", "Search", "Settings")
val selectedIcons = listOf(Icons.Filled.Home, Icons.Filled.Favorite, Icons.Filled.Star)
val unselectedIcons =
    listOf(Icons.Outlined.Home, Icons.Outlined.FavoriteBorder, Icons.Outlined.StarBorder)
val state = rememberWideNavigationRailState()
val scope = rememberCoroutineScope()

Row(Modifier.fillMaxSize()) {
    ModalWideNavigationRail(state = state, hideOnCollapse = true) {
        items.forEachIndexed { index, item ->
            WideNavigationRailItem(
                railExpanded = true,
                icon = {
                    Icon(
                        if (selectedItem == index) selectedIcons[index]
                        else unselectedIcons[index],
                        contentDescription = null
                    )
                },
                label = { Text(item) },
                selected = selectedItem == index,
                onClick = {
                    selectedItem = index
                    scope.launch { state.collapse() }
                }
            )
        }
    }

    Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
        val currentPage = items.get(selectedItem)
        Button(onClick = { scope.launch { state.expand() } }, Modifier.padding(32.dp)) {
            Text(text = "$currentPage Page\nOpen modal rail", textAlign = TextAlign.Center)
        }
    }
}

See WideNavigationRailItem for configuration specific to each item, and not the overall ModalWideNavigationRail component.

Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this wide navigation rail

state: WideNavigationRailState = rememberWideNavigationRailState()

the WideNavigationRailState of this wide navigation rail

hideOnCollapse: Boolean = false

whether this wide navigation rail should slide offscreen when it collapses and be hidden, or stay on screen as a collapsed wide navigation rail (default)

collapsedShape: Shape = WideNavigationRailDefaults.containerShape

the shape of this wide navigation rail's container when it's collapsed

expandedShape: Shape = WideNavigationRailDefaults.modalContainerShape

the shape of this wide navigation rail's container when it's expanded

colors: WideNavigationRailColors = WideNavigationRailDefaults.colors()

WideNavigationRailColors that will be used to resolve the colors used for this wide navigation rail. See WideNavigationRailDefaults.colors

header: (@Composable () -> Unit)? = null

optional header that may hold a FloatingActionButton or a logo

expandedHeaderTopPadding: Dp = 0.dp

the padding to be applied to the top of the rail. It's usually needed in order to align the content of the rail between the collapsed and expanded animation

windowInsets: WindowInsets = WideNavigationRailDefaults.windowInsets

a window insets of the wide navigation rail

arrangement: WideNavigationRailArrangement = WideNavigationRailDefaults.Arrangement

the WideNavigationRailArrangement of this wide navigation rail

expandedProperties: ModalWideNavigationRailProperties = ModalWideNavigationRailDefaults.Properties

ModalWideNavigationRailProperties for further customization of the expanded modal wide navigation rail's window behavior

content: @Composable () -> Unit

the content of this modal wide navigation rail, usually WideNavigationRailItems

MultiChoiceSegmentedButtonRow

@Composable
fun MultiChoiceSegmentedButtonRow(
    modifier: Modifier = Modifier,
    space: Dp = SegmentedButtonDefaults.BorderWidth,
    content: @Composable MultiChoiceSegmentedButtonRowScope.() -> Unit
): Unit

Material Segmented Button.

A Layout to correctly position, size, and add semantics to SegmentedButtons in a Row. It handles overlapping items so that strokes of the item are correctly on top of each other.

MultiChoiceSegmentedButtonRow is used when the selection allows multiple value, for correct semantics.

import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.TrendingUp
import androidx.compose.material.icons.filled.BookmarkBorder
import androidx.compose.material.icons.filled.StarBorder
import androidx.compose.material3.Icon
import androidx.compose.material3.MultiChoiceSegmentedButtonRow
import androidx.compose.material3.SegmentedButton
import androidx.compose.material3.SegmentedButtonDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier

val checkedList = remember { mutableStateListOf<Int>() }
val options = listOf("Favorites", "Trending", "Saved")
val icons =
    listOf(
        Icons.Filled.StarBorder,
        Icons.AutoMirrored.Filled.TrendingUp,
        Icons.Filled.BookmarkBorder
    )
MultiChoiceSegmentedButtonRow {
    options.forEachIndexed { index, label ->
        SegmentedButton(
            shape = SegmentedButtonDefaults.itemShape(index = index, count = options.size),
            icon = {
                SegmentedButtonDefaults.Icon(active = index in checkedList) {
                    Icon(
                        imageVector = icons[index],
                        contentDescription = null,
                        modifier = Modifier.size(SegmentedButtonDefaults.IconSize)
                    )
                }
            },
            onCheckedChange = {
                if (index in checkedList) {
                    checkedList.remove(index)
                } else {
                    checkedList.add(index)
                }
            },
            checked = index in checkedList
        ) {
            Text(label)
        }
    }
}
Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this row

space: Dp = SegmentedButtonDefaults.BorderWidth

the dimension of the overlap between buttons. Should be equal to the stroke width used on the items.

content: @Composable MultiChoiceSegmentedButtonRowScope.() -> Unit

the content of this Segmented Button Row, typically a sequence of SegmentedButtons

@Composable
fun NavigationBar(
    modifier: Modifier = Modifier,
    containerColor: Color = NavigationBarDefaults.containerColor,
    contentColor: Color = MaterialTheme.colorScheme.contentColorFor(containerColor),
    tonalElevation: Dp = NavigationBarDefaults.Elevation,
    windowInsets: WindowInsets = NavigationBarDefaults.windowInsets,
    content: @Composable RowScope.() -> Unit
): Unit

Material Design bottom navigation bar.

Navigation bars offer a persistent and convenient way to switch between primary destinations in an app.

Navigation bar image

NavigationBar should contain three to five NavigationBarItems, each representing a singular destination.

A simple example looks like:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Star
import androidx.compose.material.icons.outlined.FavoriteBorder
import androidx.compose.material.icons.outlined.Home
import androidx.compose.material.icons.outlined.StarBorder
import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember

var selectedItem by remember { mutableIntStateOf(0) }
val items = listOf("Songs", "Artists", "Playlists")
val selectedIcons = listOf(Icons.Filled.Home, Icons.Filled.Favorite, Icons.Filled.Star)
val unselectedIcons =
    listOf(Icons.Outlined.Home, Icons.Outlined.FavoriteBorder, Icons.Outlined.StarBorder)

NavigationBar {
    items.forEachIndexed { index, item ->
        NavigationBarItem(
            icon = {
                Icon(
                    if (selectedItem == index) selectedIcons[index] else unselectedIcons[index],
                    contentDescription = item
                )
            },
            label = { Text(item) },
            selected = selectedItem == index,
            onClick = { selectedItem = index }
        )
    }
}

See NavigationBarItem for configuration specific to each item, and not the overall NavigationBar component.

Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this navigation bar

containerColor: Color = NavigationBarDefaults.containerColor

the color used for the background of this navigation bar. Use Color.Transparent to have no color.

contentColor: Color = MaterialTheme.colorScheme.contentColorFor(containerColor)

the preferred color for content inside this navigation bar. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

tonalElevation: Dp = NavigationBarDefaults.Elevation

when containerColor is ColorScheme.surface, a translucent primary color overlay is applied on top of the container. A higher tonal elevation value will result in a darker color in light theme and lighter color in dark theme. See also: Surface.

windowInsets: WindowInsets = NavigationBarDefaults.windowInsets

a window insets of the navigation bar.

content: @Composable RowScope.() -> Unit

the content of this navigation bar, typically 3-5 NavigationBarItems

@Composable
fun NavigationDrawerItem(
    label: @Composable () -> Unit,
    selected: Boolean,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    icon: (@Composable () -> Unit)? = null,
    badge: (@Composable () -> Unit)? = null,
    shape: Shape = NavigationDrawerTokens.ActiveIndicatorShape.value,
    colors: NavigationDrawerItemColors = NavigationDrawerItemDefaults.colors(),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design navigation drawer item.

A NavigationDrawerItem represents a destination within drawers, either ModalNavigationDrawer, PermanentNavigationDrawer or DismissibleNavigationDrawer.

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material.icons.filled.Bookmarks
import androidx.compose.material.icons.filled.CalendarMonth
import androidx.compose.material.icons.filled.Dashboard
import androidx.compose.material.icons.filled.Email
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Group
import androidx.compose.material.icons.filled.Headphones
import androidx.compose.material.icons.filled.Image
import androidx.compose.material.icons.filled.JoinFull
import androidx.compose.material.icons.filled.Keyboard
import androidx.compose.material.icons.filled.Laptop
import androidx.compose.material.icons.filled.Map
import androidx.compose.material.icons.filled.Navigation
import androidx.compose.material.icons.filled.Outbox
import androidx.compose.material.icons.filled.PushPin
import androidx.compose.material.icons.filled.QrCode
import androidx.compose.material.icons.filled.Radio
import androidx.compose.material3.Button
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.Icon
import androidx.compose.material3.ModalDrawerSheet
import androidx.compose.material3.ModalNavigationDrawer
import androidx.compose.material3.NavigationDrawerItem
import androidx.compose.material3.NavigationDrawerItemDefaults
import androidx.compose.material3.Text
import androidx.compose.material3.rememberDrawerState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val drawerState = rememberDrawerState(DrawerValue.Closed)
val scope = rememberCoroutineScope()
// icons to mimic drawer destinations
val items =
    listOf(
        Icons.Default.AccountCircle,
        Icons.Default.Bookmarks,
        Icons.Default.CalendarMonth,
        Icons.Default.Dashboard,
        Icons.Default.Email,
        Icons.Default.Favorite,
        Icons.Default.Group,
        Icons.Default.Headphones,
        Icons.Default.Image,
        Icons.Default.JoinFull,
        Icons.Default.Keyboard,
        Icons.Default.Laptop,
        Icons.Default.Map,
        Icons.Default.Navigation,
        Icons.Default.Outbox,
        Icons.Default.PushPin,
        Icons.Default.QrCode,
        Icons.Default.Radio,
    )
val selectedItem = remember { mutableStateOf(items[0]) }
ModalNavigationDrawer(
    drawerState = drawerState,
    drawerContent = {
        ModalDrawerSheet(drawerState) {
            Column(Modifier.verticalScroll(rememberScrollState())) {
                Spacer(Modifier.height(12.dp))
                items.forEach { item ->
                    NavigationDrawerItem(
                        icon = { Icon(item, contentDescription = null) },
                        label = { Text(item.name.substringAfterLast(".")) },
                        selected = item == selectedItem.value,
                        onClick = {
                            scope.launch { drawerState.close() }
                            selectedItem.value = item
                        },
                        modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
                    )
                }
            }
        }
    },
    content = {
        Column(
            modifier = Modifier.fillMaxSize().padding(16.dp),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text(text = if (drawerState.isClosed) ">>> Swipe >>>" else "<<< Swipe <<<")
            Spacer(Modifier.height(20.dp))
            Button(onClick = { scope.launch { drawerState.open() } }) { Text("Click to open") }
        }
    }
)
Parameters
label: @Composable () -> Unit

text label for this item

selected: Boolean

whether this item is selected

onClick: () -> Unit

called when this item is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this item

icon: (@Composable () -> Unit)? = null

optional icon for this item, typically an Icon

badge: (@Composable () -> Unit)? = null

optional badge to show on this item from the end side

shape: Shape = NavigationDrawerTokens.ActiveIndicatorShape.value

optional shape for the active indicator

colors: NavigationDrawerItemColors = NavigationDrawerItemDefaults.colors()

NavigationDrawerItemColors that will be used to resolve the colors used for this item in different states. See NavigationDrawerItemDefaults.colors.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this item. You can use this to change the item's appearance or preview the item in different states. Note that if null is provided, interactions will still happen internally.

@Composable
fun NavigationRail(
    modifier: Modifier = Modifier,
    containerColor: Color = NavigationRailDefaults.ContainerColor,
    contentColor: Color = contentColorFor(containerColor),
    header: (@Composable ColumnScope.() -> Unit)? = null,
    windowInsets: WindowInsets = NavigationRailDefaults.windowInsets,
    content: @Composable ColumnScope.() -> Unit
): Unit

Material Design bottom navigation rail.

Navigation rails provide access to primary destinations in apps when using tablet and desktop screens.

Navigation rail image

The navigation rail should be used to display three to seven app destinations and, optionally, a FloatingActionButton or a logo header. Each destination is typically represented by an icon and an optional text label.

NavigationRail should contain multiple NavigationRailItems, each representing a singular destination.

A simple example looks like:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Star
import androidx.compose.material.icons.outlined.FavoriteBorder
import androidx.compose.material.icons.outlined.Home
import androidx.compose.material.icons.outlined.StarBorder
import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationRail
import androidx.compose.material3.NavigationRailItem
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember

var selectedItem by remember { mutableIntStateOf(0) }
val items = listOf("Home", "Search", "Settings")
val selectedIcons = listOf(Icons.Filled.Home, Icons.Filled.Favorite, Icons.Filled.Star)
val unselectedIcons =
    listOf(Icons.Outlined.Home, Icons.Outlined.FavoriteBorder, Icons.Outlined.StarBorder)
NavigationRail {
    items.forEachIndexed { index, item ->
        NavigationRailItem(
            icon = {
                Icon(
                    if (selectedItem == index) selectedIcons[index] else unselectedIcons[index],
                    contentDescription = item
                )
            },
            label = { Text(item) },
            selected = selectedItem == index,
            onClick = { selectedItem = index }
        )
    }
}

See NavigationRailItem for configuration specific to each item, and not the overall NavigationRail component.

Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this navigation rail

containerColor: Color = NavigationRailDefaults.ContainerColor

the color used for the background of this navigation rail. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this navigation rail. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

header: (@Composable ColumnScope.() -> Unit)? = null

optional header that may hold a FloatingActionButton or a logo

windowInsets: WindowInsets = NavigationRailDefaults.windowInsets

a window insets of the navigation rail.

content: @Composable ColumnScope.() -> Unit

the content of this navigation rail, typically 3-7 NavigationRailItems

@Composable
fun NavigationRailItem(
    selected: Boolean,
    onClick: () -> Unit,
    icon: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    label: (@Composable () -> Unit)? = null,
    alwaysShowLabel: Boolean = true,
    colors: NavigationRailItemColors = NavigationRailItemDefaults.colors(),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design navigation rail item.

A NavigationRailItem represents a destination within a NavigationRail.

Navigation rails provide access to primary destinations in apps when using tablet and desktop screens.

The text label is always shown (if it exists) when selected. Showing text labels if not selected is controlled by alwaysShowLabel.

Parameters
selected: Boolean

whether this item is selected

onClick: () -> Unit

called when this item is clicked

icon: @Composable () -> Unit

icon for this item, typically an Icon

modifier: Modifier = Modifier

the Modifier to be applied to this item

enabled: Boolean = true

controls the enabled state of this item. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

label: (@Composable () -> Unit)? = null

optional text label for this item

alwaysShowLabel: Boolean = true

whether to always show the label for this item. If false, the label will only be shown when this item is selected.

colors: NavigationRailItemColors = NavigationRailItemDefaults.colors()

NavigationRailItemColors that will be used to resolve the colors used for this item in different states. See NavigationRailItemDefaults.colors.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this item. You can use this to change the item's appearance or preview the item in different states. Note that if null is provided, interactions will still happen internally.

OutlinedButton

@Composable
fun OutlinedButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shape: Shape = ButtonDefaults.outlinedShape,
    colors: ButtonColors = ButtonDefaults.outlinedButtonColors(),
    elevation: ButtonElevation? = null,
    border: BorderStroke? = ButtonDefaults.outlinedButtonBorder(enabled),
    contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
    interactionSource: MutableInteractionSource? = null,
    content: @Composable RowScope.() -> Unit
): Unit

Material Design outlined button.

Buttons help people initiate actions, from sending an email, to sharing a document, to liking a post.

Outlined button image

Outlined buttons are medium-emphasis buttons. They contain actions that are important, but are not the primary action in an app. Outlined buttons pair well with Buttons to indicate an alternative, secondary action.

import androidx.compose.material3.Button
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text

OutlinedButton(onClick = { /* Do something! */ }) { Text("Outlined Button") }

Choose the best button for an action based on the amount of emphasis it needs. The more important an action is, the higher emphasis its button should be.

The default text style for internal Text components will be set to Typography.labelLarge.

Parameters
onClick: () -> Unit

called when this button is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this button

enabled: Boolean = true

controls the enabled state of this button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

shape: Shape = ButtonDefaults.outlinedShape

defines the shape of this button's container, border (when border is not null), and shadow (when using elevation).

colors: ButtonColors = ButtonDefaults.outlinedButtonColors()

ButtonColors that will be used to resolve the colors for this button in different states. See ButtonDefaults.outlinedButtonColors.

elevation: ButtonElevation? = null

ButtonElevation used to resolve the elevation for this button in different states. This controls the size of the shadow below the button. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay.

border: BorderStroke? = ButtonDefaults.outlinedButtonBorder(enabled)

the border to draw around the container of this button. Pass null for no border.

contentPadding: PaddingValues = ButtonDefaults.ContentPadding

the spacing values to apply internally between the container and the content

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this button. You can use this to change the button's appearance or preview the button in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable RowScope.() -> Unit

The content displayed on the button, expected to be text, icon or image.

OutlinedCard

@Composable
fun OutlinedCard(
    modifier: Modifier = Modifier,
    shape: Shape = CardDefaults.outlinedShape,
    colors: CardColors = CardDefaults.outlinedCardColors(),
    elevation: CardElevation = CardDefaults.outlinedCardElevation(),
    border: BorderStroke = CardDefaults.outlinedCardBorder(),
    content: @Composable ColumnScope.() -> Unit
): Unit

Material Design outlined card.

Outlined cards contain content and actions that relate information about a subject. They have a visual boundary around the container. This can provide greater emphasis than the other types.

This OutlinedCard does not handle input events - see the other OutlinedCard overloads if you want a clickable or selectable OutlinedCard.

Outlined card image

Outlined card sample:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Card
import androidx.compose.material3.OutlinedCard
import androidx.compose.material3.Text
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

OutlinedCard(Modifier.size(width = 180.dp, height = 100.dp)) {
    Box(Modifier.fillMaxSize()) { Text("Card content", Modifier.align(Alignment.Center)) }
}
Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this card

shape: Shape = CardDefaults.outlinedShape

defines the shape of this card's container, border (when border is not null), and shadow (when using elevation)

colors: CardColors = CardDefaults.outlinedCardColors()

CardColors that will be used to resolve the color(s) used for this card in different states. See CardDefaults.outlinedCardColors.

elevation: CardElevation = CardDefaults.outlinedCardElevation()

CardElevation used to resolve the elevation for this card in different states. This controls the size of the shadow below the card. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See also: Surface.

border: BorderStroke = CardDefaults.outlinedCardBorder()

the border to draw around the container of this card

content: @Composable ColumnScope.() -> Unit

The content displayed on the card

OutlinedCard

@Composable
fun OutlinedCard(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shape: Shape = CardDefaults.outlinedShape,
    colors: CardColors = CardDefaults.outlinedCardColors(),
    elevation: CardElevation = CardDefaults.outlinedCardElevation(),
    border: BorderStroke = CardDefaults.outlinedCardBorder(enabled),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable ColumnScope.() -> Unit
): Unit

Material Design outlined card.

Outlined cards contain content and actions that relate information about a subject. They have a visual boundary around the container. This can provide greater emphasis than the other types.

This OutlinedCard handles click events, calling its onClick lambda.

Outlined card image

Clickable outlined card sample:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Card
import androidx.compose.material3.OutlinedCard
import androidx.compose.material3.Text
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

OutlinedCard(
    onClick = { /* Do something */ },
    modifier = Modifier.size(width = 180.dp, height = 100.dp)
) {
    Box(Modifier.fillMaxSize()) { Text("Clickable", Modifier.align(Alignment.Center)) }
}
Parameters
onClick: () -> Unit

called when this card is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this card

enabled: Boolean = true

controls the enabled state of this card. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

shape: Shape = CardDefaults.outlinedShape

defines the shape of this card's container, border (when border is not null), and shadow (when using elevation)

colors: CardColors = CardDefaults.outlinedCardColors()

CardColors that will be used to resolve the color(s) used for this card in different states. See CardDefaults.outlinedCardColors.

elevation: CardElevation = CardDefaults.outlinedCardElevation()

CardElevation used to resolve the elevation for this card in different states. This controls the size of the shadow below the card. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See also: Surface.

border: BorderStroke = CardDefaults.outlinedCardBorder(enabled)

the border to draw around the container of this card

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this card. You can use this to change the card's appearance or preview the card in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable ColumnScope.() -> Unit

The content displayed on the card

OutlinedIconButton

@Composable
fun OutlinedIconButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shape: Shape = IconButtonDefaults.outlinedShape,
    colors: IconButtonColors = IconButtonDefaults.outlinedIconButtonColors(),
    border: BorderStroke? = IconButtonDefaults.outlinedIconButtonBorder(enabled),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable () -> Unit
): Unit

Material Design outlined icon button.

Icon buttons help people take supplementary actions with a single tap. They’re used when a compact button is required, such as in a toolbar or image list.

Outlined icon button image

Icon buttons help people take supplementary actions with a single tap. They’re used when a compact button is required, such as in a toolbar or image list.

Use this "contained" icon button when the component requires more visual separation from the background.

content should typically be an Icon (see androidx.compose.material.icons.Icons). If using a custom icon, note that the typical size for the internal icon is 24 x 24 dp. The outlined icon button has an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.OutlinedIconButton

OutlinedIconButton(onClick = { /* doSomething() */ }) {
    Icon(Icons.Filled.Lock, contentDescription = "Localized description")
}

Large-sized uniform rounded shape

import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.OutlinedIconButton
import androidx.compose.ui.Modifier

OutlinedIconButton(
    onClick = { /* doSomething() */ },
    modifier = Modifier.size(IconButtonDefaults.largeContainerSize()),
    shape = IconButtonDefaults.largeRoundShape
) {
    Icon(
        Icons.Filled.Lock,
        contentDescription = "Localized description",
        modifier = Modifier.size(IconButtonDefaults.largeIconSize)
    )
}
Parameters
onClick: () -> Unit

called when this icon button is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this icon button

enabled: Boolean = true

controls the enabled state of this icon button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

shape: Shape = IconButtonDefaults.outlinedShape

defines the shape of this icon button's container and border (when border is not null)

colors: IconButtonColors = IconButtonDefaults.outlinedIconButtonColors()

IconButtonColors that will be used to resolve the colors used for this icon button in different states. See IconButtonDefaults.outlinedIconButtonVibrantColors and IconButtonDefaults.outlinedIconButtonColors.

border: BorderStroke? = IconButtonDefaults.outlinedIconButtonBorder(enabled)

the border to draw around the container of this icon button. Pass null for no border. See IconButtonDefaults.outlinedIconButtonBorder and IconButtonDefaults.outlinedIconButtonBorder.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this icon button. You can use this to change the icon button's appearance or preview the icon button in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable () -> Unit

the content of this icon button, typically an Icon

OutlinedIconToggleButton

@Composable
fun OutlinedIconToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shape: Shape = IconButtonDefaults.outlinedShape,
    colors: IconToggleButtonColors = IconButtonDefaults.outlinedIconToggleButtonColors(),
    border: BorderStroke? = IconButtonDefaults.outlinedIconToggleButtonBorder(enabled, checked),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable () -> Unit
): Unit

Material Design outlined icon toggle button.

Icon buttons help people take supplementary actions with a single tap. They’re used when a compact button is required, such as in a toolbar or image list.

Outlined icon toggle button image

content should typically be an Icon (see androidx.compose.material.icons.Icons). If using a custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material3.Icon
import androidx.compose.material3.IconToggleButton
import androidx.compose.material3.OutlinedIconToggleButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var checked by remember { mutableStateOf(false) }
OutlinedIconToggleButton(checked = checked, onCheckedChange = { checked = it }) {
    if (checked) {
        Icon(Icons.Filled.Lock, contentDescription = "Localized description")
    } else {
        Icon(Icons.Outlined.Lock, contentDescription = "Localized description")
    }
}
Parameters
checked: Boolean

whether this icon button is toggled on or off

onCheckedChange: (Boolean) -> Unit

called when this icon button is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this icon button

enabled: Boolean = true

controls the enabled state of this icon button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

shape: Shape = IconButtonDefaults.outlinedShape

defines the shape of this icon button's container and border (when border is not null)

colors: IconToggleButtonColors = IconButtonDefaults.outlinedIconToggleButtonColors()

IconToggleButtonColors that will be used to resolve the colors used for this icon button in different states. See IconButtonDefaults.outlinedIconToggleButtonVibrantColors and IconButtonDefaults.outlinedIconToggleButtonColors.

border: BorderStroke? = IconButtonDefaults.outlinedIconToggleButtonBorder(enabled, checked)

the border to draw around the container of this icon button. Pass null for no border. See IconButtonDefaults.outlinedIconToggleButtonVibrantBorder and IconButtonDefaults.outlinedIconToggleButtonBorder.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this icon button. You can use this to change the icon button's appearance or preview the icon button in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable () -> Unit

the content of this icon button, typically an Icon

OutlinedIconToggleButton

@ExperimentalMaterial3ExpressiveApi
@Composable
fun OutlinedIconToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    shapes: IconButtonShapes,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: IconToggleButtonColors = IconButtonDefaults.outlinedIconToggleButtonVibrantColors(),
    border: BorderStroke? = IconButtonDefaults.outlinedIconToggleButtonVibrantBorder(enabled, checked),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable () -> Unit
): Unit

Material Design outlined icon toggle button.

Icon buttons help people take supplementary actions with a single tap. They’re used when a compact button is required, such as in a toolbar or image list.

Outlined icon toggle button image

content should typically be an Icon (see androidx.compose.material.icons.Icons). If using a custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.IconButtonShapes
import androidx.compose.material3.IconToggleButton
import androidx.compose.material3.OutlinedIconToggleButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var checked by remember { mutableStateOf(false) }
OutlinedIconToggleButton(
    checked = checked,
    onCheckedChange = { checked = it },
    shapes =
        IconButtonShapes(
            shape = IconButtonDefaults.smallRoundShape,
            pressedShape = IconButtonDefaults.smallPressedShape,
            checkedShape = IconButtonDefaults.smallSquareShape,
        )
) {
    if (checked) {
        Icon(Icons.Filled.Lock, contentDescription = "Localized description")
    } else {
        Icon(Icons.Outlined.Lock, contentDescription = "Localized description")
    }
}
Parameters
checked: Boolean

whether this icon button is toggled on or off

onCheckedChange: (Boolean) -> Unit

called when this icon button is clicked

shapes: IconButtonShapes

the IconButtonShapes that the icon toggle button will morph between depending on the user's interaction with the icon toggle button.

modifier: Modifier = Modifier

the Modifier to be applied to this icon button

enabled: Boolean = true

controls the enabled state of this icon button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

colors: IconToggleButtonColors = IconButtonDefaults.outlinedIconToggleButtonVibrantColors()

IconToggleButtonColors that will be used to resolve the colors used for this icon button in different states. See IconButtonDefaults.outlinedIconToggleButtonVibrantColors.

border: BorderStroke? = IconButtonDefaults.outlinedIconToggleButtonVibrantBorder(enabled, checked)

the border to draw around the container of this icon button. Pass null for no border. See IconButtonDefaults.outlinedIconToggleButtonVibrantBorder.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this icon button. You can use this to change the icon button's appearance or preview the icon button in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable () -> Unit

the content of this icon button, typically an Icon

OutlinedSecureTextField

@Composable
fun OutlinedSecureTextField(
    state: TextFieldState,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    textStyle: TextStyle = LocalTextStyle.current,
    labelPosition: TextFieldLabelPosition = TextFieldLabelPosition.Attached(),
    label: (@Composable TextFieldLabelScope.() -> Unit)? = null,
    placeholder: (@Composable () -> Unit)? = null,
    leadingIcon: (@Composable () -> Unit)? = null,
    trailingIcon: (@Composable () -> Unit)? = null,
    prefix: (@Composable () -> Unit)? = null,
    suffix: (@Composable () -> Unit)? = null,
    supportingText: (@Composable () -> Unit)? = null,
    isError: Boolean = false,
    inputTransformation: InputTransformation? = null,
    textObfuscationMode: TextObfuscationMode = TextObfuscationMode.RevealLastTyped,
    textObfuscationCharacter: Char = DefaultObfuscationCharacter,
    keyboardOptions: KeyboardOptions = SecureTextFieldKeyboardOptions,
    onKeyboardAction: KeyboardActionHandler? = null,
    onTextLayout: (Density.(getResult: () -> TextLayoutResult?) -> Unit)? = null,
    shape: Shape = OutlinedTextFieldDefaults.shape,
    colors: TextFieldColors = OutlinedTextFieldDefaults.colors(),
    contentPadding: PaddingValues = OutlinedTextFieldDefaults.contentPadding(),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design outlined text field for secure content.

Text fields allow users to enter text into a UI. OutlinedSecureTextField is specifically designed for password entry fields. It only supports a single line of content and comes with default settings that are appropriate for entering secure content. Additionally, some context menu actions like cut, copy, and drag are disabled for added security.

Outlined text fields have less visual emphasis than filled text fields. When they appear in places like forms, where many text fields are placed together, their reduced emphasis helps simplify the layout. For a filled version, see SecureTextField.

Parameters
state: TextFieldState

TextFieldState object that holds the internal editing state of the text field.

modifier: Modifier = Modifier

the Modifier to be applied to this text field.

enabled: Boolean = true

controls the enabled state of this text field. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

textStyle: TextStyle = LocalTextStyle.current

the style to be applied to the input text. Defaults to LocalTextStyle.

labelPosition: TextFieldLabelPosition = TextFieldLabelPosition.Attached()

the position of the label. See TextFieldLabelPosition.

label: (@Composable TextFieldLabelScope.() -> Unit)? = null

the optional label to be displayed with this text field. The default text style uses Typography.bodySmall when minimized and Typography.bodyLarge when expanded.

placeholder: (@Composable () -> Unit)? = null

the optional placeholder to be displayed when the input text is empty. The default text style uses Typography.bodyLarge.

leadingIcon: (@Composable () -> Unit)? = null

the optional leading icon to be displayed at the beginning of the text field container.

trailingIcon: (@Composable () -> Unit)? = null

the optional trailing icon to be displayed at the end of the text field container.

prefix: (@Composable () -> Unit)? = null

the optional prefix to be displayed before the input text in the text field.

suffix: (@Composable () -> Unit)? = null

the optional suffix to be displayed after the input text in the text field.

supportingText: (@Composable () -> Unit)? = null

the optional supporting text to be displayed below the text field.

isError: Boolean = false

indicates if the text field's current value is in error. When true, the components of the text field will be displayed in an error color, and an error will be announced to accessibility services.

inputTransformation: InputTransformation? = null

optional InputTransformation that will be used to transform changes to the TextFieldState made by the user. The transformation will be applied to changes made by hardware and software keyboard events, pasting or dropping text, accessibility services, and tests. The transformation will not be applied when changing the state programmatically, or when the transformation is changed. If the transformation is changed on an existing text field, it will be applied to the next user edit. The transformation will not immediately affect the current state.

textObfuscationMode: TextObfuscationMode = TextObfuscationMode.RevealLastTyped

the method used to obscure the input text.

textObfuscationCharacter: Char = DefaultObfuscationCharacter

the character to use while obfuscating the text. It doesn't have an effect when textObfuscationMode is set to TextObfuscationMode.Visible.

keyboardOptions: KeyboardOptions = SecureTextFieldKeyboardOptions

software keyboard options that contains configuration such as KeyboardType and ImeAction. This component by default configures KeyboardOptions for a secure text field by disabling auto correct and setting KeyboardType to KeyboardType.Password.

onKeyboardAction: KeyboardActionHandler? = null

called when the user presses the action button in the input method editor (IME), or by pressing the enter key on a hardware keyboard. By default this parameter is null, and would execute the default behavior for a received IME Action e.g., ImeAction.Done would close the keyboard, ImeAction.Next would switch the focus to the next focusable item on the screen.

onTextLayout: (Density.(getResult: () -> TextLayoutResult?) -> Unit)? = null

Callback that is executed when the text layout becomes queryable. The callback receives a function that returns a TextLayoutResult if the layout can be calculated, or null if it cannot. The function reads the layout result from a snapshot state object, and will invalidate its caller when the layout result changes. A TextLayoutResult object contains paragraph information, size of the text, baselines and other details. Density scope is the one that was used while creating the given text layout.

shape: Shape = OutlinedTextFieldDefaults.shape

defines the shape of this text field's container.

colors: TextFieldColors = OutlinedTextFieldDefaults.colors()

TextFieldColors that will be used to resolve the colors used for this text field in different states. See TextFieldDefaults.colors.

contentPadding: PaddingValues = OutlinedTextFieldDefaults.contentPadding()

the padding applied to the inner text field that separates it from the surrounding elements of the text field. Note that the padding values may not be respected if they are incompatible with the text field's size constraints or layout. See TextFieldDefaults.contentPaddingWithLabel and TextFieldDefaults.contentPaddingWithoutLabel.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this text field. You can use this to change the text field's appearance or preview the text field in different states. Note that if null is provided, interactions will still happen internally.

OutlinedTextField

@Composable
fun OutlinedTextField(
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    readOnly: Boolean = false,
    textStyle: TextStyle = LocalTextStyle.current,
    label: (@Composable () -> Unit)? = null,
    placeholder: (@Composable () -> Unit)? = null,
    leadingIcon: (@Composable () -> Unit)? = null,
    trailingIcon: (@Composable () -> Unit)? = null,
    prefix: (@Composable () -> Unit)? = null,
    suffix: (@Composable () -> Unit)? = null,
    supportingText: (@Composable () -> Unit)? = null,
    isError: Boolean = false,
    visualTransformation: VisualTransformation = VisualTransformation.None,
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
    keyboardActions: KeyboardActions = KeyboardActions.Default,
    singleLine: Boolean = false,
    maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
    minLines: Int = 1,
    interactionSource: MutableInteractionSource? = null,
    shape: Shape = OutlinedTextFieldDefaults.shape,
    colors: TextFieldColors = OutlinedTextFieldDefaults.colors()
): Unit

Material Design outlined text field.

Text fields allow users to enter text into a UI. They typically appear in forms and dialogs. Outlined text fields have less visual emphasis than filled text fields. When they appear in places like forms, where many text fields are placed together, their reduced emphasis helps simplify the layout.

Outlined text field image

If apart from input text change you also want to observe the cursor location, selection range, or IME composition use the OutlinedTextField overload with the TextFieldValue parameter instead.

Parameters
value: String

the input text to be shown in the text field

onValueChange: (String) -> Unit

the callback that is triggered when the input service updates the text. An updated text comes as a parameter of the callback

modifier: Modifier = Modifier

the Modifier to be applied to this text field

enabled: Boolean = true

controls the enabled state of this text field. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

readOnly: Boolean = false

controls the editable state of the text field. When true, the text field cannot be modified. However, a user can focus it and copy text from it. Read-only text fields are usually used to display pre-filled forms that a user cannot edit.

textStyle: TextStyle = LocalTextStyle.current

the style to be applied to the input text. Defaults to LocalTextStyle.

label: (@Composable () -> Unit)? = null

the optional label to be displayed with this text field. The default text style uses Typography.bodySmall when minimized and Typography.bodyLarge when expanded.

placeholder: (@Composable () -> Unit)? = null

the optional placeholder to be displayed when the text field is in focus and the input text is empty. The default text style for internal Text is Typography.bodyLarge

leadingIcon: (@Composable () -> Unit)? = null

the optional leading icon to be displayed at the beginning of the text field container

trailingIcon: (@Composable () -> Unit)? = null

the optional trailing icon to be displayed at the end of the text field container

prefix: (@Composable () -> Unit)? = null

the optional prefix to be displayed before the input text in the text field

suffix: (@Composable () -> Unit)? = null

the optional suffix to be displayed after the input text in the text field

supportingText: (@Composable () -> Unit)? = null

the optional supporting text to be displayed below the text field

isError: Boolean = false

indicates if the text field's current value is in error. If set to true, the label, bottom indicator and trailing icon by default will be displayed in error color

visualTransformation: VisualTransformation = VisualTransformation.None

transforms the visual representation of the input value For example, you can use PasswordVisualTransformation to create a password text field. By default, no visual transformation is applied.

keyboardOptions: KeyboardOptions = KeyboardOptions.Default

software keyboard options that contains configuration such as KeyboardType and ImeAction

keyboardActions: KeyboardActions = KeyboardActions.Default

when the input service emits an IME action, the corresponding callback is called. Note that this IME action may be different from what you specified in KeyboardOptions.imeAction

singleLine: Boolean = false

when true, this text field becomes a single horizontally scrolling text field instead of wrapping onto multiple lines. The keyboard will be informed to not show the return key as the ImeAction. Note that maxLines parameter will be ignored as the maxLines attribute will be automatically set to 1.

maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE

the maximum height in terms of maximum number of visible lines. It is required that 1 <= minLines<= maxLines. This parameter is ignored when singleLine is true.

minLines: Int = 1

the minimum height in terms of minimum number of visible lines. It is required that 1 <= minLines<= maxLines. This parameter is ignored when singleLine is true.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this text field. You can use this to change the text field's appearance or preview the text field in different states. Note that if null is provided, interactions will still happen internally.

shape: Shape = OutlinedTextFieldDefaults.shape

defines the shape of this text field's border

colors: TextFieldColors = OutlinedTextFieldDefaults.colors()

TextFieldColors that will be used to resolve the colors used for this text field in different states. See OutlinedTextFieldDefaults.colors.

OutlinedTextField

@Composable
fun OutlinedTextField(
    value: TextFieldValue,
    onValueChange: (TextFieldValue) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    readOnly: Boolean = false,
    textStyle: TextStyle = LocalTextStyle.current,
    label: (@Composable () -> Unit)? = null,
    placeholder: (@Composable () -> Unit)? = null,
    leadingIcon: (@Composable () -> Unit)? = null,
    trailingIcon: (@Composable () -> Unit)? = null,
    prefix: (@Composable () -> Unit)? = null,
    suffix: (@Composable () -> Unit)? = null,
    supportingText: (@Composable () -> Unit)? = null,
    isError: Boolean = false,
    visualTransformation: VisualTransformation = VisualTransformation.None,
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
    keyboardActions: KeyboardActions = KeyboardActions.Default,
    singleLine: Boolean = false,
    maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
    minLines: Int = 1,
    interactionSource: MutableInteractionSource? = null,
    shape: Shape = OutlinedTextFieldDefaults.shape,
    colors: TextFieldColors = OutlinedTextFieldDefaults.colors()
): Unit

Material Design outlined text field.

Text fields allow users to enter text into a UI. They typically appear in forms and dialogs. Outlined text fields have less visual emphasis than filled text fields. When they appear in places like forms, where many text fields are placed together, their reduced emphasis helps simplify the layout.

Outlined text field image

This overload provides access to the input text, cursor position and selection range and IME composition. If you only want to observe an input text change, use the OutlinedTextField overload with the String parameter instead.

Parameters
value: TextFieldValue

the input TextFieldValue to be shown in the text field

onValueChange: (TextFieldValue) -> Unit

the callback that is triggered when the input service updates values in TextFieldValue. An updated TextFieldValue comes as a parameter of the callback

modifier: Modifier = Modifier

the Modifier to be applied to this text field

enabled: Boolean = true

controls the enabled state of this text field. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

readOnly: Boolean = false

controls the editable state of the text field. When true, the text field cannot be modified. However, a user can focus it and copy text from it. Read-only text fields are usually used to display pre-filled forms that a user cannot edit.

textStyle: TextStyle = LocalTextStyle.current

the style to be applied to the input text. Defaults to LocalTextStyle.

label: (@Composable () -> Unit)? = null

the optional label to be displayed with this text field. The default text style uses Typography.bodySmall when minimized and Typography.bodyLarge when expanded.

placeholder: (@Composable () -> Unit)? = null

the optional placeholder to be displayed when the text field is in focus and the input text is empty. The default text style for internal Text is Typography.bodyLarge

leadingIcon: (@Composable () -> Unit)? = null

the optional leading icon to be displayed at the beginning of the text field container

trailingIcon: (@Composable () -> Unit)? = null

the optional trailing icon to be displayed at the end of the text field container

prefix: (@Composable () -> Unit)? = null

the optional prefix to be displayed before the input text in the text field

suffix: (@Composable () -> Unit)? = null

the optional suffix to be displayed after the input text in the text field

supportingText: (@Composable () -> Unit)? = null

the optional supporting text to be displayed below the text field

isError: Boolean = false

indicates if the text field's current value is in error state. If set to true, the label, bottom indicator and trailing icon by default will be displayed in error color

visualTransformation: VisualTransformation = VisualTransformation.None

transforms the visual representation of the input value For example, you can use PasswordVisualTransformation to create a password text field. By default, no visual transformation is applied.

keyboardOptions: KeyboardOptions = KeyboardOptions.Default

software keyboard options that contains configuration such as KeyboardType and ImeAction

keyboardActions: KeyboardActions = KeyboardActions.Default

when the input service emits an IME action, the corresponding callback is called. Note that this IME action may be different from what you specified in KeyboardOptions.imeAction

singleLine: Boolean = false

when true, this text field becomes a single horizontally scrolling text field instead of wrapping onto multiple lines. The keyboard will be informed to not show the return key as the ImeAction. Note that maxLines parameter will be ignored as the maxLines attribute will be automatically set to 1.

maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE

the maximum height in terms of maximum number of visible lines. It is required that 1 <= minLines<= maxLines. This parameter is ignored when singleLine is true.

minLines: Int = 1

the minimum height in terms of minimum number of visible lines. It is required that 1 <= minLines<= maxLines. This parameter is ignored when singleLine is true.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this text field. You can use this to change the text field's appearance or preview the text field in different states. Note that if null is provided, interactions will still happen internally.

shape: Shape = OutlinedTextFieldDefaults.shape

defines the shape of this text field's border

colors: TextFieldColors = OutlinedTextFieldDefaults.colors()

TextFieldColors that will be used to resolve the colors used for this text field in different states. See OutlinedTextFieldDefaults.colors.

OutlinedTextField

@Composable
fun OutlinedTextField(
    state: TextFieldState,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    readOnly: Boolean = false,
    textStyle: TextStyle = LocalTextStyle.current,
    labelPosition: TextFieldLabelPosition = TextFieldLabelPosition.Attached(),
    label: (@Composable TextFieldLabelScope.() -> Unit)? = null,
    placeholder: (@Composable () -> Unit)? = null,
    leadingIcon: (@Composable () -> Unit)? = null,
    trailingIcon: (@Composable () -> Unit)? = null,
    prefix: (@Composable () -> Unit)? = null,
    suffix: (@Composable () -> Unit)? = null,
    supportingText: (@Composable () -> Unit)? = null,
    isError: Boolean = false,
    inputTransformation: InputTransformation? = null,
    outputTransformation: OutputTransformation? = null,
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
    onKeyboardAction: KeyboardActionHandler? = null,
    lineLimits: TextFieldLineLimits = TextFieldLineLimits.Default,
    onTextLayout: (Density.(getResult: () -> TextLayoutResult?) -> Unit)? = null,
    scrollState: ScrollState = rememberScrollState(),
    shape: Shape = OutlinedTextFieldDefaults.shape,
    colors: TextFieldColors = OutlinedTextFieldDefaults.colors(),
    contentPadding: PaddingValues = OutlinedTextFieldDefaults.contentPadding(),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design outlined text field.

Text fields allow users to enter text into a UI. They typically appear in forms and dialogs. Outlined text fields have less visual emphasis than filled text fields. When they appear in places like forms, where many text fields are placed together, their reduced emphasis helps simplify the layout.

Outlined text field image

If you are looking for a filled version, see TextField. For a text field specifically designed for passwords or other secure content, see OutlinedSecureTextField.

This overload of OutlinedTextField uses TextFieldState to keep track of its text content and position of the cursor or selection.

See example usage:

import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.remember

OutlinedTextField(
    state = rememberTextFieldState(),
    lineLimits = TextFieldLineLimits.SingleLine,
    label = { Text("Label") },
)
import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.remember
import androidx.compose.ui.text.TextRange

val state = rememberTextFieldState("Initial text", TextRange(0, 12))
OutlinedTextField(
    state = state,
    lineLimits = TextFieldLineLimits.SingleLine,
    label = { Text("Label") },
)
Parameters
state: TextFieldState

TextFieldState object that holds the internal editing state of the text field.

modifier: Modifier = Modifier

the Modifier to be applied to this text field.

enabled: Boolean = true

controls the enabled state of this text field. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

readOnly: Boolean = false

controls the editable state of the text field. When true, the text field cannot be modified. However, a user can focus it and copy text from it. Read-only text fields are usually used to display pre-filled forms that a user cannot edit.

textStyle: TextStyle = LocalTextStyle.current

the style to be applied to the input text. Defaults to LocalTextStyle.

labelPosition: TextFieldLabelPosition = TextFieldLabelPosition.Attached()

the position of the label. See TextFieldLabelPosition.

label: (@Composable TextFieldLabelScope.() -> Unit)? = null

the optional label to be displayed with this text field. The default text style uses Typography.bodySmall when minimized and Typography.bodyLarge when expanded.

placeholder: (@Composable () -> Unit)? = null

the optional placeholder to be displayed when the input text is empty. The default text style uses Typography.bodyLarge.

leadingIcon: (@Composable () -> Unit)? = null

the optional leading icon to be displayed at the beginning of the text field container.

trailingIcon: (@Composable () -> Unit)? = null

the optional trailing icon to be displayed at the end of the text field container.

prefix: (@Composable () -> Unit)? = null

the optional prefix to be displayed before the input text in the text field.

suffix: (@Composable () -> Unit)? = null

the optional suffix to be displayed after the input text in the text field.

supportingText: (@Composable () -> Unit)? = null

the optional supporting text to be displayed below the text field.

isError: Boolean = false

indicates if the text field's current value is in error. When true, the components of the text field will be displayed in an error color, and an error will be announced to accessibility services.

inputTransformation: InputTransformation? = null

optional InputTransformation that will be used to transform changes to the TextFieldState made by the user. The transformation will be applied to changes made by hardware and software keyboard events, pasting or dropping text, accessibility services, and tests. The transformation will not be applied when changing the state programmatically, or when the transformation is changed. If the transformation is changed on an existing text field, it will be applied to the next user edit. The transformation will not immediately affect the current state.

outputTransformation: OutputTransformation? = null

optional OutputTransformation that transforms how the contents of the text field are presented.

keyboardOptions: KeyboardOptions = KeyboardOptions.Default

software keyboard options that contains configuration such as KeyboardType and ImeAction.

onKeyboardAction: KeyboardActionHandler? = null

called when the user presses the action button in the input method editor (IME), or by pressing the enter key on a hardware keyboard. By default this parameter is null, and would execute the default behavior for a received IME Action e.g., ImeAction.Done would close the keyboard, ImeAction.Next would switch the focus to the next focusable item on the screen.

lineLimits: TextFieldLineLimits = TextFieldLineLimits.Default

whether the text field should be SingleLine, scroll horizontally, and ignore newlines; or MultiLine and grow and scroll vertically. If SingleLine is passed, all newline characters ('\n') within the text will be replaced with regular whitespace (' ').

onTextLayout: (Density.(getResult: () -> TextLayoutResult?) -> Unit)? = null

Callback that is executed when the text layout becomes queryable. The callback receives a function that returns a TextLayoutResult if the layout can be calculated, or null if it cannot. The function reads the layout result from a snapshot state object, and will invalidate its caller when the layout result changes. A TextLayoutResult object contains paragraph information, size of the text, baselines and other details. Density scope is the one that was used while creating the given text layout.

scrollState: ScrollState = rememberScrollState()

scroll state that manages either horizontal or vertical scroll of the text field. If lineLimits is SingleLine, this text field is treated as single line with horizontal scroll behavior. Otherwise, the text field becomes vertically scrollable.

shape: Shape = OutlinedTextFieldDefaults.shape

defines the shape of this text field's border.

colors: TextFieldColors = OutlinedTextFieldDefaults.colors()

TextFieldColors that will be used to resolve the colors used for this text field in different states. See OutlinedTextFieldDefaults.colors.

contentPadding: PaddingValues = OutlinedTextFieldDefaults.contentPadding()

the padding applied to the inner text field that separates it from the surrounding elements of the text field. Note that the padding values may not be respected if they are incompatible with the text field's size constraints or layout. See OutlinedTextFieldDefaults.contentPadding.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this text field. You can use this to change the text field's appearance or preview the text field in different states. Note that if null is provided, interactions will still happen internally.

OutlinedToggleButton

@Composable
@ExperimentalMaterial3ExpressiveApi
fun OutlinedToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shapes: ButtonShapes = ToggleButtonDefaults.shapes(),
    colors: ToggleButtonColors = ToggleButtonDefaults.outlinedToggleButtonColors(),
    elevation: ButtonElevation? = null,
    border: BorderStroke? = ButtonDefaults.outlinedButtonBorder(enabled),
    contentPadding: PaddingValues = ToggleButtonDefaults.ContentPadding,
    interactionSource: MutableInteractionSource? = null,
    content: @Composable RowScope.() -> Unit
): Unit

TODO link to mio page when available.

Toggle button is a toggleable button that switches between primary and tonal colors depending on checked's value. It also morphs between the three shapes provided in shapes depending on the state of the interaction with the toggle button as long as the three shapes provided our CornerBasedShapes. If a shape in shapes isn't a CornerBasedShape, then toggle button will toggle between the ButtonShapes according to user interaction.

TODO link to an image when available

Outlined toggle buttons are medium-emphasis buttons. They contain actions that are important, but are not the primary action in an app. Outlined buttons pair well with ToggleButtons to indicate an alternative, secondary action.

see OutlinedButton for a static button that doesn't need to be toggled. see OutlinedIconToggleButton for a toggleable button where the content is specifically an Icon.

import androidx.compose.material3.OutlinedToggleButton
import androidx.compose.material3.Text
import androidx.compose.material3.ToggleButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var checked by remember { mutableStateOf(false) }
OutlinedToggleButton(checked = checked, onCheckedChange = { checked = it }) {
    Text("Outlined Button")
}
Parameters
checked: Boolean

whether the toggle button is toggled on or off.

onCheckedChange: (Boolean) -> Unit

called when the toggle button is clicked.

modifier: Modifier = Modifier

the Modifier to be applied to the toggle button.

enabled: Boolean = true

controls the enabled state of this toggle button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

shapes: ButtonShapes = ToggleButtonDefaults.shapes()

the ButtonShapes that the toggle button will morph between depending on the user's interaction with the toggle button.

colors: ToggleButtonColors = ToggleButtonDefaults.outlinedToggleButtonColors()

ToggleButtonColors that will be used to resolve the colors used for this toggle button in different states. See ToggleButtonDefaults.outlinedToggleButtonColors.

elevation: ButtonElevation? = null

ButtonElevation used to resolve the elevation for this button in different states. This controls the size of the shadow below the button. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay.

border: BorderStroke? = ButtonDefaults.outlinedButtonBorder(enabled)

the border to draw around the container of this toggle button.

contentPadding: PaddingValues = ToggleButtonDefaults.ContentPadding

the spacing values to apply internally between the container and the content

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this toggle button. You can use this to change the toggle button's appearance or preview the toggle button in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable RowScope.() -> Unit

The content displayed on the toggle button, expected to be text, icon or image.

PermanentDrawerSheet

@Composable
fun PermanentDrawerSheet(
    modifier: Modifier = Modifier,
    drawerShape: Shape = RectangleShape,
    drawerContainerColor: Color = DrawerDefaults.standardContainerColor,
    drawerContentColor: Color = contentColorFor(drawerContainerColor),
    drawerTonalElevation: Dp = DrawerDefaults.PermanentDrawerElevation,
    windowInsets: WindowInsets = DrawerDefaults.windowInsets,
    content: @Composable ColumnScope.() -> Unit
): Unit

Content inside of a permanent navigation drawer.

Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this drawer's content

drawerShape: Shape = RectangleShape

defines the shape of this drawer's container

drawerContainerColor: Color = DrawerDefaults.standardContainerColor

the color used for the background of this drawer. Use Color.Transparent to have no color.

drawerContentColor: Color = contentColorFor(drawerContainerColor)

the preferred color for content inside this drawer. Defaults to either the matching content color for drawerContainerColor, or to the current LocalContentColor if drawerContainerColor is not a color from the theme.

drawerTonalElevation: Dp = DrawerDefaults.PermanentDrawerElevation

when drawerContainerColor is ColorScheme.surface, a translucent primary color overlay is applied on top of the container. A higher tonal elevation value will result in a darker color in light theme and lighter color in dark theme. See also: Surface.

windowInsets: WindowInsets = DrawerDefaults.windowInsets

a window insets for the sheet.

content: @Composable ColumnScope.() -> Unit

content inside a permanent navigation drawer

PermanentNavigationDrawer

@Composable
fun PermanentNavigationDrawer(
    drawerContent: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
): Unit

Material Design navigation permanent drawer.

Navigation drawers provide ergonomic access to destinations in an app. They’re often next to app content and affect the screen’s layout grid.

Navigation drawer image

The permanent navigation drawer is always visible and usually used for frequently switching destinations. On mobile screens, use ModalNavigationDrawer instead.

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material.icons.filled.Bookmarks
import androidx.compose.material.icons.filled.CalendarMonth
import androidx.compose.material.icons.filled.Dashboard
import androidx.compose.material.icons.filled.Email
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Group
import androidx.compose.material.icons.filled.Headphones
import androidx.compose.material.icons.filled.Image
import androidx.compose.material.icons.filled.JoinFull
import androidx.compose.material.icons.filled.Keyboard
import androidx.compose.material.icons.filled.Laptop
import androidx.compose.material.icons.filled.Map
import androidx.compose.material.icons.filled.Navigation
import androidx.compose.material.icons.filled.Outbox
import androidx.compose.material.icons.filled.PushPin
import androidx.compose.material.icons.filled.QrCode
import androidx.compose.material.icons.filled.Radio
import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationDrawerItem
import androidx.compose.material3.PermanentDrawerSheet
import androidx.compose.material3.PermanentNavigationDrawer
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

// icons to mimic drawer destinations
val items =
    listOf(
        Icons.Default.AccountCircle,
        Icons.Default.Bookmarks,
        Icons.Default.CalendarMonth,
        Icons.Default.Dashboard,
        Icons.Default.Email,
        Icons.Default.Favorite,
        Icons.Default.Group,
        Icons.Default.Headphones,
        Icons.Default.Image,
        Icons.Default.JoinFull,
        Icons.Default.Keyboard,
        Icons.Default.Laptop,
        Icons.Default.Map,
        Icons.Default.Navigation,
        Icons.Default.Outbox,
        Icons.Default.PushPin,
        Icons.Default.QrCode,
        Icons.Default.Radio,
    )
val selectedItem = remember { mutableStateOf(items[0]) }
PermanentNavigationDrawer(
    drawerContent = {
        PermanentDrawerSheet(Modifier.width(240.dp)) {
            Column(Modifier.verticalScroll(rememberScrollState())) {
                Spacer(Modifier.height(12.dp))
                items.forEach { item ->
                    NavigationDrawerItem(
                        icon = { Icon(item, contentDescription = null) },
                        label = { Text(item.name.substringAfterLast(".")) },
                        selected = item == selectedItem.value,
                        onClick = { selectedItem.value = item },
                        modifier = Modifier.padding(horizontal = 12.dp)
                    )
                }
            }
        }
    },
    content = {
        Column(
            modifier = Modifier.fillMaxSize().padding(16.dp),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text(text = "Application content")
        }
    }
)
Parameters
drawerContent: @Composable () -> Unit

content inside this drawer

modifier: Modifier = Modifier

the Modifier to be applied to this drawer

content: @Composable () -> Unit

content of the rest of the UI

PrimaryScrollableTabRow

@ExperimentalMaterial3Api
@Composable
fun PrimaryScrollableTabRow(
    selectedTabIndex: Int,
    modifier: Modifier = Modifier,
    scrollState: ScrollState = rememberScrollState(),
    containerColor: Color = TabRowDefaults.primaryContainerColor,
    contentColor: Color = TabRowDefaults.primaryContentColor,
    edgePadding: Dp = TabRowDefaults.ScrollableTabRowEdgeStartPadding,
    indicator: @Composable TabIndicatorScope.() -> Unit = @Composable { TabRowDefaults.PrimaryIndicator( Modifier.tabIndicatorOffset(selectedTabIndex, matchContentSize = true), width = Dp.Unspecified, ) },
    divider: @Composable () -> Unit = @Composable { HorizontalDivider() },
    tabs: @Composable () -> Unit
): Unit

Material Design Scrollable Primary tabs

Primary tabs are placed at the top of the content pane under a top app bar. They display the main content destinations. When a set of tabs cannot fit on screen, use scrollable tabs. Scrollable tabs can use longer text labels and a larger number of tabs. They are best used for browsing on touch interfaces.

A scrollable tab row contains a row of Tabs, and displays an indicator underneath the currently selected tab. A scrollable tab row places its tabs offset from the starting edge, and allows scrolling to tabs that are placed off screen. For a fixed tab row that does not allow scrolling, and evenly places its tabs, see PrimaryTabRow.

Parameters
selectedTabIndex: Int

the index of the currently selected tab

modifier: Modifier = Modifier

the Modifier to be applied to this tab row

scrollState: ScrollState = rememberScrollState()

the ScrollState of this tab row

containerColor: Color = TabRowDefaults.primaryContainerColor

the color used for the background of this tab row. Use Color.Transparent to have no color.

contentColor: Color = TabRowDefaults.primaryContentColor

the preferred color for content inside this tab row. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

edgePadding: Dp = TabRowDefaults.ScrollableTabRowEdgeStartPadding

the padding between the starting and ending edge of the scrollable tab row, and the tabs inside the row. This padding helps inform the user that this tab row can be scrolled, unlike a TabRow.

indicator: @Composable TabIndicatorScope.() -> Unit = @Composable { TabRowDefaults.PrimaryIndicator( Modifier.tabIndicatorOffset(selectedTabIndex, matchContentSize = true), width = Dp.Unspecified, ) }

the indicator that represents which tab is currently selected. By default this will be a TabRowDefaults.PrimaryIndicator, using a TabRowDefaults.tabIndicatorOffset modifier to animate its position.

divider: @Composable () -> Unit = @Composable { HorizontalDivider() }

the divider displayed at the bottom of the tab row. This provides a layer of separation between the tab row and the content displayed underneath.

tabs: @Composable () -> Unit

the tabs inside this tab row. Typically this will be multiple Tabs. Each element inside this lambda will be measured and placed evenly across the row, each taking up equal space.

@ExperimentalMaterial3Api
@Composable
fun PrimaryTabRow(
    selectedTabIndex: Int,
    modifier: Modifier = Modifier,
    containerColor: Color = TabRowDefaults.primaryContainerColor,
    contentColor: Color = TabRowDefaults.primaryContentColor,
    indicator: @Composable TabIndicatorScope.() -> Unit = { TabRowDefaults.PrimaryIndicator( modifier = Modifier.tabIndicatorOffset(selectedTabIndex, matchContentSize = true), width = Dp.Unspecified, ) },
    divider: @Composable () -> Unit = @Composable { HorizontalDivider() },
    tabs: @Composable () -> Unit
): Unit

Material Design Fixed Primary tabs

Primary tabs are placed at the top of the content pane under a top app bar. They display the main content destinations. Fixed tabs display all tabs in a set simultaneously. They are best for switching between related content quickly, such as between transportation methods in a map. To navigate between fixed tabs, tap an individual tab, or swipe left or right in the content area.

A TabRow contains a row of Tabs, and displays an indicator underneath the currently selected tab. A TabRow places its tabs evenly spaced along the entire row, with each tab taking up an equal amount of space. See PrimaryScrollableTabRow for a tab row that does not enforce equal size, and allows scrolling to tabs that do not fit on screen.

A simple example with text tabs looks like:

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.PrimaryTabRow
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow

var state by remember { mutableStateOf(0) }
val titles = listOf("Tab 1", "Tab 2", "Tab 3 with lots of text")
Column {
    PrimaryTabRow(selectedTabIndex = state) {
        titles.forEachIndexed { index, title ->
            Tab(
                selected = state == index,
                onClick = { state = index },
                text = { Text(text = title, maxLines = 2, overflow = TextOverflow.Ellipsis) }
            )
        }
    }
    Text(
        modifier = Modifier.align(Alignment.CenterHorizontally),
        text = "Primary tab ${state + 1} selected",
        style = MaterialTheme.typography.bodyLarge
    )
}

You can also provide your own custom tab, such as:

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SecondaryTabRow
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

var state by remember { mutableStateOf(0) }
val titles = listOf("Tab 1", "Tab 2", "Tab 3")
Column {
    SecondaryTabRow(selectedTabIndex = state) {
        titles.forEachIndexed { index, title ->
            FancyTab(title = title, onClick = { state = index }, selected = (index == state))
        }
    }
    Text(
        modifier = Modifier.align(Alignment.CenterHorizontally),
        text = "Fancy tab ${state + 1} selected",
        style = MaterialTheme.typography.bodyLarge
    )
}

Where the custom tab itself could look like:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

Tab(selected, onClick) {
    Column(
        Modifier.padding(10.dp).height(50.dp).fillMaxWidth(),
        verticalArrangement = Arrangement.SpaceBetween
    ) {
        Box(
            Modifier.size(10.dp)
                .align(Alignment.CenterHorizontally)
                .background(
                    color =
                        if (selected) MaterialTheme.colorScheme.primary
                        else MaterialTheme.colorScheme.background
                )
        )
        Text(
            text = title,
            style = MaterialTheme.typography.bodyLarge,
            modifier = Modifier.align(Alignment.CenterHorizontally)
        )
    }
}

As well as customizing the tab, you can also provide a custom indicator, to customize the indicator displayed for a tab. indicator will be placed to fill the entire TabRow, so it should internally take care of sizing and positioning the indicator to match changes to selectedTabIndex.

For example, given an indicator that draws a rounded rectangle near the edges of the Tab:

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Tab
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.unit.dp

// Draws a rounded rectangular with border around the Tab, with a 5.dp padding from the edges
// Color is passed in as a parameter [color]
Box(
    modifier
        .padding(5.dp)
        .fillMaxSize()
        .border(BorderStroke(2.dp, color), RoundedCornerShape(5.dp))
)

We can reuse TabRowDefaults.tabIndicatorOffset and just provide this indicator, as we aren't changing how the size and position of the indicator changes between tabs:

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SecondaryTabRow
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

var state by remember { mutableStateOf(0) }
val titles = listOf("Tab 1", "Tab 2", "Tab 3")

Column {
    SecondaryTabRow(
        selectedTabIndex = state,
        indicator = {
            FancyIndicator(
                MaterialTheme.colorScheme.primary,
                Modifier.tabIndicatorOffset(state)
            )
        }
    ) {
        titles.forEachIndexed { index, title ->
            Tab(selected = state == index, onClick = { state = index }, text = { Text(title) })
        }
    }
    Text(
        modifier = Modifier.align(Alignment.CenterHorizontally),
        text = "Fancy indicator tab ${state + 1} selected",
        style = MaterialTheme.typography.bodyLarge
    )
}

You may also want to use a custom transition, to allow you to dynamically change the appearance of the indicator as it animates between tabs, such as changing its color or size. indicator is stacked on top of the entire TabRow, so you just need to provide a custom transition that animates the offset of the indicator from the start of the TabRow. For example, take the following example that uses a transition to animate the offset, width, and color of the same FancyIndicator from before, also adding a physics based 'spring' effect to the indicator in the direction of motion:

import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.AnimationVector1D
import androidx.compose.animation.core.VectorConverter
import androidx.compose.animation.core.spring
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Tab
import androidx.compose.material3.TabPosition
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.layout.Measurable
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp

val colors =
    listOf(
        MaterialTheme.colorScheme.primary,
        MaterialTheme.colorScheme.secondary,
        MaterialTheme.colorScheme.tertiary,
    )
var startAnimatable by remember { mutableStateOf<Animatable<Dp, AnimationVector1D>?>(null) }
var endAnimatable by remember { mutableStateOf<Animatable<Dp, AnimationVector1D>?>(null) }
val coroutineScope = rememberCoroutineScope()
val indicatorColor: Color by animateColorAsState(colors[index % colors.size], label = "")

Box(
    Modifier.tabIndicatorLayout {
            measurable: Measurable,
            constraints: Constraints,
            tabPositions: List<TabPosition> ->
            val newStart = tabPositions[index].left
            val newEnd = tabPositions[index].right
            val startAnim =
                startAnimatable
                    ?: Animatable(newStart, Dp.VectorConverter).also { startAnimatable = it }

            val endAnim =
                endAnimatable
                    ?: Animatable(newEnd, Dp.VectorConverter).also { endAnimatable = it }

            if (endAnim.targetValue != newEnd) {
                coroutineScope.launch {
                    endAnim.animateTo(
                        newEnd,
                        animationSpec =
                            if (endAnim.targetValue < newEnd) {
                                spring(dampingRatio = 1f, stiffness = 1000f)
                            } else {
                                spring(dampingRatio = 1f, stiffness = 50f)
                            }
                    )
                }
            }

            if (startAnim.targetValue != newStart) {
                coroutineScope.launch {
                    startAnim.animateTo(
                        newStart,
                        animationSpec =
                            // Handle directionality here, if we are moving to the right, we
                            // want the right side of the indicator to move faster, if we are
                            // moving to the left, we want the left side to move faster.
                            if (startAnim.targetValue < newStart) {
                                spring(dampingRatio = 1f, stiffness = 50f)
                            } else {
                                spring(dampingRatio = 1f, stiffness = 1000f)
                            }
                    )
                }
            }

            val indicatorEnd = endAnim.value.roundToPx()
            val indicatorStart = startAnim.value.roundToPx()

            // Apply an offset from the start to correctly position the indicator around the tab
            val placeable =
                measurable.measure(
                    constraints.copy(
                        maxWidth = indicatorEnd - indicatorStart,
                        minWidth = indicatorEnd - indicatorStart,
                    )
                )
            layout(constraints.maxWidth, constraints.maxHeight) {
                placeable.place(indicatorStart, 0)
            }
        }
        .padding(5.dp)
        .fillMaxSize()
        .drawWithContent {
            drawRoundRect(
                color = indicatorColor,
                cornerRadius = CornerRadius(5.dp.toPx()),
                style = Stroke(width = 2.dp.toPx())
            )
        }
)

We can now just pass this indicator directly to TabRow:

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SecondaryTabRow
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

var state by remember { mutableStateOf(0) }
val titles = listOf("Tab 1", "Tab 2", "Tab 3")

Column {
    SecondaryTabRow(
        selectedTabIndex = state,
        indicator = { FancyAnimatedIndicatorWithModifier(state) }
    ) {
        titles.forEachIndexed { index, title ->
            Tab(selected = state == index, onClick = { state = index }, text = { Text(title) })
        }
    }
    Text(
        modifier = Modifier.align(Alignment.CenterHorizontally),
        text = "Fancy transition tab ${state + 1} selected",
        style = MaterialTheme.typography.bodyLarge
    )
}
Parameters
selectedTabIndex: Int

the index of the currently selected tab

modifier: Modifier = Modifier

the Modifier to be applied to this tab row

containerColor: Color = TabRowDefaults.primaryContainerColor

the color used for the background of this tab row. Use Color.Transparent to have no color.

contentColor: Color = TabRowDefaults.primaryContentColor

the preferred color for content inside this tab row. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

indicator: @Composable TabIndicatorScope.() -> Unit = { TabRowDefaults.PrimaryIndicator( modifier = Modifier.tabIndicatorOffset(selectedTabIndex, matchContentSize = true), width = Dp.Unspecified, ) }

the indicator that represents which tab is currently selected. By default this will be a TabRowDefaults.PrimaryIndicator, using a TabRowDefaults.tabIndicatorOffset modifier to animate its position.

divider: @Composable () -> Unit = @Composable { HorizontalDivider() }

the divider displayed at the bottom of the tab row. This provides a layer of separation between the tab row and the content displayed underneath.

tabs: @Composable () -> Unit

the tabs inside this tab row. Typically this will be multiple Tabs. Each element inside this lambda will be measured and placed evenly across the row, each taking up equal space.

ProvideTextStyle

@Composable
fun ProvideTextStyle(value: TextStyle, content: @Composable () -> Unit): Unit

This function is used to set the current value of LocalTextStyle, merging the given style with the current style values for any missing attributes. Any Text components included in this component's content will be styled with this style unless styled explicitly.

See also
LocalTextStyle

RadioButton

@Composable
fun RadioButton(
    selected: Boolean,
    onClick: (() -> Unit)?,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: RadioButtonColors = RadioButtonDefaults.colors(),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design radio button.

Radio buttons allow users to select one option from a set.

Radio button image

import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.selection.selectable
import androidx.compose.foundation.selection.selectableGroup
import androidx.compose.material3.RadioButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics

// We have two radio buttons and only one can be selected
var state by remember { mutableStateOf(true) }
// Note that Modifier.selectableGroup() is essential to ensure correct accessibility behavior.
// We also set a content description for this sample, but note that a RadioButton would usually
// be part of a higher level component, such as a raw with text, and that component would need
// to provide an appropriate content description. See RadioGroupSample.
Row(Modifier.selectableGroup()) {
    RadioButton(
        selected = state,
        onClick = { state = true },
        modifier = Modifier.semantics { contentDescription = "Localized Description" }
    )
    RadioButton(
        selected = !state,
        onClick = { state = false },
        modifier = Modifier.semantics { contentDescription = "Localized Description" }
    )
}

RadioButtons can be combined together with Text in the desired layout (e.g. Column or Row) to achieve radio group-like behaviour, where the entire layout is selectable:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.selection.selectable
import androidx.compose.foundation.selection.selectableGroup
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.dp

val radioOptions = listOf("Calls", "Missed", "Friends")
val (selectedOption, onOptionSelected) = remember { mutableStateOf(radioOptions[0]) }
// Note that Modifier.selectableGroup() is essential to ensure correct accessibility behavior
Column(Modifier.selectableGroup()) {
    radioOptions.forEach { text ->
        Row(
            Modifier.fillMaxWidth()
                .height(56.dp)
                .selectable(
                    selected = (text == selectedOption),
                    onClick = { onOptionSelected(text) },
                    role = Role.RadioButton
                )
                .padding(horizontal = 16.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            RadioButton(
                selected = (text == selectedOption),
                onClick = null // null recommended for accessibility with screenreaders
            )
            Text(
                text = text,
                style = MaterialTheme.typography.bodyLarge,
                modifier = Modifier.padding(start = 16.dp)
            )
        }
    }
}
Parameters
selected: Boolean

whether this radio button is selected or not

onClick: (() -> Unit)?

called when this radio button is clicked. If null, then this radio button will not be interactable, unless something else handles its input events and updates its state.

modifier: Modifier = Modifier

the Modifier to be applied to this radio button

enabled: Boolean = true

controls the enabled state of this radio button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

colors: RadioButtonColors = RadioButtonDefaults.colors()

RadioButtonColors that will be used to resolve the color used for this radio button in different states. See RadioButtonDefaults.colors.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this radio button. You can use this to change the radio button's appearance or preview the radio button in different states. Note that if null is provided, interactions will still happen internally.

RangeSlider

@Composable
fun RangeSlider(
    value: ClosedFloatingPointRange<Float>,
    onValueChange: (ClosedFloatingPointRange<Float>) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    valueRange: ClosedFloatingPointRange<Float> = 0f..1f,
    steps: @IntRange(from = 0) Int = 0,
    onValueChangeFinished: (() -> Unit)? = null,
    colors: SliderColors = SliderDefaults.colors()
): Unit

Material Design Range slider.

Range Sliders expand upon Slider using the same concepts but allow the user to select 2 values.

The two values are still bounded by the value range but they also cannot cross each other.

Use continuous Range Sliders to allow users to make meaningful selections that don’t require a specific values:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.RangeSlider
import androidx.compose.material3.RangeSliderState
import androidx.compose.material3.Slider
import androidx.compose.material3.SliderState
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

val rangeSliderState = remember {
    RangeSliderState(
        0f,
        100f,
        valueRange = 0f..100f,
        onValueChangeFinished = {
            // launch some business logic update with the state you hold
            // viewModel.updateSelectedSliderValue(sliderPosition)
        }
    )
}
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    val rangeStart = "%.2f".format(rangeSliderState.activeRangeStart)
    val rangeEnd = "%.2f".format(rangeSliderState.activeRangeEnd)
    Text(text = "$rangeStart .. $rangeEnd")
    RangeSlider(
        state = rangeSliderState,
        modifier = Modifier.semantics { contentDescription = "Localized Description" }
    )
}

You can allow the user to choose only between predefined set of values by specifying the amount of steps between min and max values:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.RangeSlider
import androidx.compose.material3.RangeSliderState
import androidx.compose.material3.Slider
import androidx.compose.material3.SliderState
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

val rangeSliderState = remember {
    RangeSliderState(
        0f,
        100f,
        valueRange = 0f..100f,
        onValueChangeFinished = {
            // launch some business logic update with the state you hold
            // viewModel.updateSelectedSliderValue(sliderPosition)
        },
        // Only allow multiples of 10. Excluding the endpoints of `valueRange`,
        // there are 9 steps (10, 20, ..., 90).
        steps = 9
    )
}
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    val rangeStart = rangeSliderState.activeRangeStart.roundToInt()
    val rangeEnd = rangeSliderState.activeRangeEnd.roundToInt()
    Text(text = "$rangeStart .. $rangeEnd")
    RangeSlider(
        state = rangeSliderState,
        modifier = Modifier.semantics { contentDescription = "Localized Description" }
    )
}
Parameters
value: ClosedFloatingPointRange<Float>

current values of the RangeSlider. If either value is outside of valueRange provided, it will be coerced to this range.

onValueChange: (ClosedFloatingPointRange<Float>) -> Unit

lambda in which values should be updated

modifier: Modifier = Modifier

modifiers for the Range Slider layout

enabled: Boolean = true

whether or not component is enabled and can we interacted with or not

valueRange: ClosedFloatingPointRange<Float> = 0f..1f

range of values that Range Slider values can take. Passed value will be coerced to this range

steps: @IntRange(from = 0) Int = 0

if positive, specifies the amount of discrete allowable values (in addition to the endpoints of the value range). Step values are evenly distributed across the range. If 0, the range slider will behave continuously and allow any value from the range. Must not be negative.

onValueChangeFinished: (() -> Unit)? = null

lambda to be invoked when value change has ended. This callback shouldn't be used to update the range slider values (use onValueChange for that), but rather to know when the user has completed selecting a new value by ending a drag or a click.

colors: SliderColors = SliderDefaults.colors()

SliderColors that will be used to determine the color of the Range Slider parts in different state. See SliderDefaults.colors to customize.

RangeSlider

@Composable
@ExperimentalMaterial3Api
fun RangeSlider(
    state: RangeSliderState,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: SliderColors = SliderDefaults.colors(),
    startInteractionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    endInteractionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    startThumb: @Composable (RangeSliderState) -> Unit = { SliderDefaults.Thumb( interactionSource = startInteractionSource, colors = colors, enabled = enabled ) },
    endThumb: @Composable (RangeSliderState) -> Unit = { SliderDefaults.Thumb( interactionSource = endInteractionSource, colors = colors, enabled = enabled ) },
    track: @Composable (RangeSliderState) -> Unit = { rangeSliderState -> SliderDefaults.Track( colors = colors, enabled = enabled, rangeSliderState = rangeSliderState ) }
): Unit

Material Design Range slider.

Range Sliders expand upon Slider using the same concepts but allow the user to select 2 values.

The two values are still bounded by the value range but they also cannot cross each other.

It uses the provided startThumb for the slider's start thumb and endThumb for the slider's end thumb. It also uses the provided track for the slider's track. If nothing is passed for these parameters, it will use SliderDefaults.Thumb and SliderDefaults.Track for the thumbs and track.

Use continuous Range Sliders to allow users to make meaningful selections that don’t require a specific values:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.RangeSlider
import androidx.compose.material3.RangeSliderState
import androidx.compose.material3.Slider
import androidx.compose.material3.SliderState
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

val rangeSliderState = remember {
    RangeSliderState(
        0f,
        100f,
        valueRange = 0f..100f,
        onValueChangeFinished = {
            // launch some business logic update with the state you hold
            // viewModel.updateSelectedSliderValue(sliderPosition)
        }
    )
}
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    val rangeStart = "%.2f".format(rangeSliderState.activeRangeStart)
    val rangeEnd = "%.2f".format(rangeSliderState.activeRangeEnd)
    Text(text = "$rangeStart .. $rangeEnd")
    RangeSlider(
        state = rangeSliderState,
        modifier = Modifier.semantics { contentDescription = "Localized Description" }
    )
}

You can allow the user to choose only between predefined set of values by specifying the amount of steps between min and max values:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.RangeSlider
import androidx.compose.material3.RangeSliderState
import androidx.compose.material3.Slider
import androidx.compose.material3.SliderState
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

val rangeSliderState = remember {
    RangeSliderState(
        0f,
        100f,
        valueRange = 0f..100f,
        onValueChangeFinished = {
            // launch some business logic update with the state you hold
            // viewModel.updateSelectedSliderValue(sliderPosition)
        },
        // Only allow multiples of 10. Excluding the endpoints of `valueRange`,
        // there are 9 steps (10, 20, ..., 90).
        steps = 9
    )
}
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    val rangeStart = rangeSliderState.activeRangeStart.roundToInt()
    val rangeEnd = rangeSliderState.activeRangeEnd.roundToInt()
    Text(text = "$rangeStart .. $rangeEnd")
    RangeSlider(
        state = rangeSliderState,
        modifier = Modifier.semantics { contentDescription = "Localized Description" }
    )
}

A custom start/end thumb and track can be provided:

import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.material3.Label
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.RangeSlider
import androidx.compose.material3.RangeSliderState
import androidx.compose.material3.Slider
import androidx.compose.material3.SliderDefaults
import androidx.compose.material3.SliderState
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

val rangeSliderState = remember {
    RangeSliderState(
        0f,
        100f,
        valueRange = 0f..100f,
        onValueChangeFinished = {
            // launch some business logic update with the state you hold
            // viewModel.updateSelectedSliderValue(sliderPosition)
        }
    )
}
val startInteractionSource = remember { MutableInteractionSource() }
val endInteractionSource = remember { MutableInteractionSource() }
val startThumbAndTrackColors =
    SliderDefaults.colors(thumbColor = Color.Blue, activeTrackColor = Color.Red)
val endThumbColors = SliderDefaults.colors(thumbColor = Color.Green)
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    RangeSlider(
        state = rangeSliderState,
        modifier = Modifier.semantics { contentDescription = "Localized Description" },
        startInteractionSource = startInteractionSource,
        endInteractionSource = endInteractionSource,
        startThumb = {
            Label(
                label = {
                    PlainTooltip(modifier = Modifier.sizeIn(45.dp, 25.dp).wrapContentWidth()) {
                        Text("%.2f".format(rangeSliderState.activeRangeStart))
                    }
                },
                interactionSource = startInteractionSource
            ) {
                SliderDefaults.Thumb(
                    interactionSource = startInteractionSource,
                    colors = startThumbAndTrackColors
                )
            }
        },
        endThumb = {
            Label(
                label = {
                    PlainTooltip(
                        modifier = Modifier.requiredSize(45.dp, 25.dp).wrapContentWidth()
                    ) {
                        Text("%.2f".format(rangeSliderState.activeRangeEnd))
                    }
                },
                interactionSource = endInteractionSource
            ) {
                SliderDefaults.Thumb(
                    interactionSource = endInteractionSource,
                    colors = endThumbColors
                )
            }
        },
        track = { rangeSliderState ->
            SliderDefaults.Track(
                colors = startThumbAndTrackColors,
                rangeSliderState = rangeSliderState
            )
        }
    )
}
Parameters
state: RangeSliderState

RangeSliderState which contains the current values of the RangeSlider.

modifier: Modifier = Modifier

modifiers for the Range Slider layout

enabled: Boolean = true

whether or not component is enabled and can we interacted with or not

colors: SliderColors = SliderDefaults.colors()

SliderColors that will be used to determine the color of the Range Slider parts in different state. See SliderDefaults.colors to customize.

startInteractionSource: MutableInteractionSource = remember { MutableInteractionSource() }

the MutableInteractionSource representing the stream of Interactions for the start thumb. You can create and pass in your own remembered instance to observe.

endInteractionSource: MutableInteractionSource = remember { MutableInteractionSource() }

the MutableInteractionSource representing the stream of Interactions for the end thumb. You can create and pass in your own remembered instance to observe.

startThumb: @Composable (RangeSliderState) -> Unit = { SliderDefaults.Thumb( interactionSource = startInteractionSource, colors = colors, enabled = enabled ) }

the start thumb to be displayed on the Range Slider. The lambda receives a RangeSliderState which is used to obtain the current active track.

endThumb: @Composable (RangeSliderState) -> Unit = { SliderDefaults.Thumb( interactionSource = endInteractionSource, colors = colors, enabled = enabled ) }

the end thumb to be displayed on the Range Slider. The lambda receives a RangeSliderState which is used to obtain the current active track.

track: @Composable (RangeSliderState) -> Unit = { rangeSliderState -> SliderDefaults.Track( colors = colors, enabled = enabled, rangeSliderState = rangeSliderState ) }

the track to be displayed on the range slider, it is placed underneath the thumb. The lambda receives a RangeSliderState which is used to obtain the current active track.

RangeSlider

@Composable
@ExperimentalMaterial3Api
fun RangeSlider(
    value: ClosedFloatingPointRange<Float>,
    onValueChange: (ClosedFloatingPointRange<Float>) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    valueRange: ClosedFloatingPointRange<Float> = 0f..1f,
    onValueChangeFinished: (() -> Unit)? = null,
    colors: SliderColors = SliderDefaults.colors(),
    startInteractionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    endInteractionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    startThumb: @Composable (RangeSliderState) -> Unit = { SliderDefaults.Thumb( interactionSource = startInteractionSource, colors = colors, enabled = enabled ) },
    endThumb: @Composable (RangeSliderState) -> Unit = { SliderDefaults.Thumb( interactionSource = endInteractionSource, colors = colors, enabled = enabled ) },
    track: @Composable (RangeSliderState) -> Unit = { rangeSliderState -> SliderDefaults.Track( colors = colors, enabled = enabled, rangeSliderState = rangeSliderState ) },
    steps: @IntRange(from = 0) Int = 0
): Unit

Material Design Range slider.

Range Sliders expand upon Slider using the same concepts but allow the user to select 2 values.

The two values are still bounded by the value range but they also cannot cross each other.

It uses the provided startThumb for the slider's start thumb and endThumb for the slider's end thumb. It also uses the provided track for the slider's track. If nothing is passed for these parameters, it will use SliderDefaults.Thumb and SliderDefaults.Track for the thumbs and track.

Use continuous Range Sliders to allow users to make meaningful selections that don’t require a specific values:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.RangeSlider
import androidx.compose.material3.RangeSliderState
import androidx.compose.material3.Slider
import androidx.compose.material3.SliderState
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

val rangeSliderState = remember {
    RangeSliderState(
        0f,
        100f,
        valueRange = 0f..100f,
        onValueChangeFinished = {
            // launch some business logic update with the state you hold
            // viewModel.updateSelectedSliderValue(sliderPosition)
        }
    )
}
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    val rangeStart = "%.2f".format(rangeSliderState.activeRangeStart)
    val rangeEnd = "%.2f".format(rangeSliderState.activeRangeEnd)
    Text(text = "$rangeStart .. $rangeEnd")
    RangeSlider(
        state = rangeSliderState,
        modifier = Modifier.semantics { contentDescription = "Localized Description" }
    )
}

You can allow the user to choose only between predefined set of values by specifying the amount of steps between min and max values:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.RangeSlider
import androidx.compose.material3.RangeSliderState
import androidx.compose.material3.Slider
import androidx.compose.material3.SliderState
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

val rangeSliderState = remember {
    RangeSliderState(
        0f,
        100f,
        valueRange = 0f..100f,
        onValueChangeFinished = {
            // launch some business logic update with the state you hold
            // viewModel.updateSelectedSliderValue(sliderPosition)
        },
        // Only allow multiples of 10. Excluding the endpoints of `valueRange`,
        // there are 9 steps (10, 20, ..., 90).
        steps = 9
    )
}
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    val rangeStart = rangeSliderState.activeRangeStart.roundToInt()
    val rangeEnd = rangeSliderState.activeRangeEnd.roundToInt()
    Text(text = "$rangeStart .. $rangeEnd")
    RangeSlider(
        state = rangeSliderState,
        modifier = Modifier.semantics { contentDescription = "Localized Description" }
    )
}

A custom start/end thumb and track can be provided:

import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.material3.Label
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.RangeSlider
import androidx.compose.material3.RangeSliderState
import androidx.compose.material3.Slider
import androidx.compose.material3.SliderDefaults
import androidx.compose.material3.SliderState
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

val rangeSliderState = remember {
    RangeSliderState(
        0f,
        100f,
        valueRange = 0f..100f,
        onValueChangeFinished = {
            // launch some business logic update with the state you hold
            // viewModel.updateSelectedSliderValue(sliderPosition)
        }
    )
}
val startInteractionSource = remember { MutableInteractionSource() }
val endInteractionSource = remember { MutableInteractionSource() }
val startThumbAndTrackColors =
    SliderDefaults.colors(thumbColor = Color.Blue, activeTrackColor = Color.Red)
val endThumbColors = SliderDefaults.colors(thumbColor = Color.Green)
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    RangeSlider(
        state = rangeSliderState,
        modifier = Modifier.semantics { contentDescription = "Localized Description" },
        startInteractionSource = startInteractionSource,
        endInteractionSource = endInteractionSource,
        startThumb = {
            Label(
                label = {
                    PlainTooltip(modifier = Modifier.sizeIn(45.dp, 25.dp).wrapContentWidth()) {
                        Text("%.2f".format(rangeSliderState.activeRangeStart))
                    }
                },
                interactionSource = startInteractionSource
            ) {
                SliderDefaults.Thumb(
                    interactionSource = startInteractionSource,
                    colors = startThumbAndTrackColors
                )
            }
        },
        endThumb = {
            Label(
                label = {
                    PlainTooltip(
                        modifier = Modifier.requiredSize(45.dp, 25.dp).wrapContentWidth()
                    ) {
                        Text("%.2f".format(rangeSliderState.activeRangeEnd))
                    }
                },
                interactionSource = endInteractionSource
            ) {
                SliderDefaults.Thumb(
                    interactionSource = endInteractionSource,
                    colors = endThumbColors
                )
            }
        },
        track = { rangeSliderState ->
            SliderDefaults.Track(
                colors = startThumbAndTrackColors,
                rangeSliderState = rangeSliderState
            )
        }
    )
}
Parameters
value: ClosedFloatingPointRange<Float>

current values of the RangeSlider. If either value is outside of valueRange provided, it will be coerced to this range.

onValueChange: (ClosedFloatingPointRange<Float>) -> Unit

lambda in which values should be updated

modifier: Modifier = Modifier

modifiers for the Range Slider layout

enabled: Boolean = true

whether or not component is enabled and can we interacted with or not

valueRange: ClosedFloatingPointRange<Float> = 0f..1f

range of values that Range Slider values can take. Passed value will be coerced to this range.

onValueChangeFinished: (() -> Unit)? = null

lambda to be invoked when value change has ended. This callback shouldn't be used to update the range slider values (use onValueChange for that), but rather to know when the user has completed selecting a new value by ending a drag or a click.

colors: SliderColors = SliderDefaults.colors()

SliderColors that will be used to determine the color of the Range Slider parts in different state. See SliderDefaults.colors to customize.

startInteractionSource: MutableInteractionSource = remember { MutableInteractionSource() }

the MutableInteractionSource representing the stream of Interactions for the start thumb. You can create and pass in your own remembered instance to observe.

endInteractionSource: MutableInteractionSource = remember { MutableInteractionSource() }

the MutableInteractionSource representing the stream of Interactions for the end thumb. You can create and pass in your own remembered instance to observe.

startThumb: @Composable (RangeSliderState) -> Unit = { SliderDefaults.Thumb( interactionSource = startInteractionSource, colors = colors, enabled = enabled ) }

the start thumb to be displayed on the Range Slider. The lambda receives a RangeSliderState which is used to obtain the current active track.

endThumb: @Composable (RangeSliderState) -> Unit = { SliderDefaults.Thumb( interactionSource = endInteractionSource, colors = colors, enabled = enabled ) }

the end thumb to be displayed on the Range Slider. The lambda receives a RangeSliderState which is used to obtain the current active track.

track: @Composable (RangeSliderState) -> Unit = { rangeSliderState -> SliderDefaults.Track( colors = colors, enabled = enabled, rangeSliderState = rangeSliderState ) }

the track to be displayed on the range slider, it is placed underneath the thumb. The lambda receives a RangeSliderState which is used to obtain the current active track.

steps: @IntRange(from = 0) Int = 0

if positive, specifies the amount of discrete allowable values (in addition to the endpoints of the value range). Step values are evenly distributed across the range. If 0, the range slider will behave continuously and allow any value from the range. Must not be negative.

@Composable
fun Scaffold(
    modifier: Modifier = Modifier,
    topBar: @Composable () -> Unit = {},
    bottomBar: @Composable () -> Unit = {},
    snackbarHost: @Composable () -> Unit = {},
    floatingActionButton: @Composable () -> Unit = {},
    floatingActionButtonPosition: FabPosition = FabPosition.End,
    containerColor: Color = MaterialTheme.colorScheme.background,
    contentColor: Color = contentColorFor(containerColor),
    contentWindowInsets: WindowInsets = ScaffoldDefaults.contentWindowInsets,
    content: @Composable (PaddingValues) -> Unit
): Unit

Material Design layout.

Scaffold implements the basic material design visual layout structure.

This component provides API to put together several material components to construct your screen, by ensuring proper layout strategy for them and collecting necessary data so these components will work together correctly.

Simple example of a Scaffold with SmallTopAppBar, FloatingActionButton:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FabPosition
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

val colors =
    listOf(
        Color(0xFFffd7d7.toInt()),
        Color(0xFFffe9d6.toInt()),
        Color(0xFFfffbd0.toInt()),
        Color(0xFFe3ffd9.toInt()),
        Color(0xFFd0fff8.toInt())
    )

Scaffold(
    topBar = {
        TopAppBar(
            title = { Text("Simple Scaffold Screen") },
            navigationIcon = {
                IconButton(onClick = { /* "Open nav drawer" */ }) {
                    Icon(Icons.Filled.Menu, contentDescription = "Localized description")
                }
            }
        )
    },
    floatingActionButtonPosition = FabPosition.End,
    floatingActionButton = {
        ExtendedFloatingActionButton(onClick = { /* fab click handler */ }) { Text("Inc") }
    },
    content = { innerPadding ->
        LazyColumn(
            // consume insets as scaffold doesn't do it by default
            modifier = Modifier.consumeWindowInsets(innerPadding),
            contentPadding = innerPadding
        ) {
            items(count = 100) {
                Box(Modifier.fillMaxWidth().height(50.dp).background(colors[it % colors.size]))
            }
        }
    }
)

To show a Snackbar, use SnackbarHostState.showSnackbar.

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Snackbar
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier

val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
Scaffold(
    snackbarHost = { SnackbarHost(snackbarHostState) },
    floatingActionButton = {
        var clickCount by remember { mutableStateOf(0) }
        ExtendedFloatingActionButton(
            onClick = {
                // show snackbar as a suspend function
                scope.launch { snackbarHostState.showSnackbar("Snackbar # ${++clickCount}") }
            }
        ) {
            Text("Show snackbar")
        }
    },
    content = { innerPadding ->
        Text(
            text = "Body content",
            modifier = Modifier.padding(innerPadding).fillMaxSize().wrapContentSize()
        )
    }
)
Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this scaffold

topBar: @Composable () -> Unit = {}

top app bar of the screen, typically a SmallTopAppBar

bottomBar: @Composable () -> Unit = {}

bottom bar of the screen, typically a NavigationBar

snackbarHost: @Composable () -> Unit = {}

component to host Snackbars that are pushed to be shown via SnackbarHostState.showSnackbar, typically a SnackbarHost

floatingActionButton: @Composable () -> Unit = {}

Main action button of the screen, typically a FloatingActionButton

floatingActionButtonPosition: FabPosition = FabPosition.End

position of the FAB on the screen. See FabPosition.

containerColor: Color = MaterialTheme.colorScheme.background

the color used for the background of this scaffold. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this scaffold. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

contentWindowInsets: WindowInsets = ScaffoldDefaults.contentWindowInsets

window insets to be passed to content slot via PaddingValues params. Scaffold will take the insets into account from the top/bottom only if the topBar/ bottomBar are not present, as the scaffold expect topBar/bottomBar to handle insets instead. Any insets consumed by other insets padding modifiers or consumeWindowInsets on a parent layout will be excluded from contentWindowInsets.

content: @Composable (PaddingValues) -> Unit

content of the screen. The lambda receives a PaddingValues that should be applied to the content root via Modifier.padding and Modifier.consumeWindowInsets to properly offset top and bottom bars. If using Modifier.verticalScroll, apply this modifier to the child of the scroll, and not on the scroll itself.

ScrollableTabRow

@Composable
fun ScrollableTabRow(
    selectedTabIndex: Int,
    modifier: Modifier = Modifier,
    containerColor: Color = TabRowDefaults.primaryContainerColor,
    contentColor: Color = TabRowDefaults.primaryContentColor,
    edgePadding: Dp = TabRowDefaults.ScrollableTabRowEdgeStartPadding,
    indicator: @Composable (tabPositions: List<TabPosition>) -> Unit = @Composable { tabPositions -> TabRowDefaults.SecondaryIndicator( Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex]) ) },
    divider: @Composable () -> Unit = @Composable { HorizontalDivider() },
    tabs: @Composable () -> Unit
): Unit

Material Design tabs

Material Design scrollable tabs.

For primary indicator tabs, use PrimaryScrollableTabRow. For secondary indicator tabs, use SecondaryScrollableTabRow.

When a set of tabs cannot fit on screen, use scrollable tabs. Scrollable tabs can use longer text labels and a larger number of tabs. They are best used for browsing on touch interfaces.

A ScrollableTabRow contains a row of Tabs, and displays an indicator underneath the currently selected tab. A ScrollableTabRow places its tabs offset from the starting edge, and allows scrolling to tabs that are placed off screen. For a fixed tab row that does not allow scrolling, and evenly places its tabs, see TabRow.

Parameters
selectedTabIndex: Int

the index of the currently selected tab

modifier: Modifier = Modifier

the Modifier to be applied to this tab row

containerColor: Color = TabRowDefaults.primaryContainerColor

the color used for the background of this tab row. Use Color.Transparent to have no color.

contentColor: Color = TabRowDefaults.primaryContentColor

the preferred color for content inside this tab row. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

edgePadding: Dp = TabRowDefaults.ScrollableTabRowEdgeStartPadding

the padding between the starting and ending edge of the scrollable tab row, and the tabs inside the row. This padding helps inform the user that this tab row can be scrolled, unlike a TabRow.

indicator: @Composable (tabPositions: List<TabPosition>) -> Unit = @Composable { tabPositions -> TabRowDefaults.SecondaryIndicator( Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex]) ) }

the indicator that represents which tab is currently selected. By default this will be a TabRowDefaults.SecondaryIndicator, using a TabRowDefaults.tabIndicatorOffset modifier to animate its position. Note that this indicator will be forced to fill up the entire tab row, so you should use TabRowDefaults.tabIndicatorOffset or similar to animate the actual drawn indicator inside this space, and provide an offset from the start.

divider: @Composable () -> Unit = @Composable { HorizontalDivider() }

the divider displayed at the bottom of the tab row. This provides a layer of separation between the tab row and the content displayed underneath.

tabs: @Composable () -> Unit

the tabs inside this tab row. Typically this will be multiple Tabs. Each element inside this lambda will be measured and placed evenly across the row, each taking up equal space.

@ExperimentalMaterial3Api
@Composable
fun SearchBar(
    inputField: @Composable () -> Unit,
    expanded: Boolean,
    onExpandedChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    shape: Shape = SearchBarDefaults.inputFieldShape,
    colors: SearchBarColors = SearchBarDefaults.colors(),
    tonalElevation: Dp = SearchBarDefaults.TonalElevation,
    shadowElevation: Dp = SearchBarDefaults.ShadowElevation,
    windowInsets: WindowInsets = SearchBarDefaults.windowInsets,
    content: @Composable ColumnScope.() -> Unit
): Unit

Material Design search.

A search bar represents a floating search field that allows users to enter a keyword or phrase and get relevant information. It can be used as a way to navigate through an app via search queries.

A search bar expands into a search "view" and can be used to display dynamic suggestions or search results.

Search bar image

A SearchBar tries to occupy the entirety of its allowed size in the expanded state. For full-screen behavior as specified by Material guidelines, parent layouts of the SearchBar must not pass any Constraints that limit its size, and the host activity should set WindowCompat.setDecorFitsSystemWindows(window, false).

If this expansion behavior is undesirable, for example on large tablet screens, DockedSearchBar can be used instead.

An example looks like:

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.filled.Star
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.ListItemDefaults
import androidx.compose.material3.SearchBar
import androidx.compose.material3.SearchBarDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.semantics.isTraversalGroup
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.traversalIndex
import androidx.compose.ui.unit.dp

val textFieldState = rememberTextFieldState()
var expanded by rememberSaveable { mutableStateOf(false) }

Box(Modifier.fillMaxSize().semantics { isTraversalGroup = true }) {
    SearchBar(
        modifier = Modifier.align(Alignment.TopCenter).semantics { traversalIndex = 0f },
        inputField = {
            SearchBarDefaults.InputField(
                state = textFieldState,
                onSearch = { expanded = false },
                expanded = expanded,
                onExpandedChange = { expanded = it },
                placeholder = { Text("Hinted search text") },
                leadingIcon = { Icon(Icons.Default.Search, contentDescription = null) },
                trailingIcon = { Icon(Icons.Default.MoreVert, contentDescription = null) },
            )
        },
        expanded = expanded,
        onExpandedChange = { expanded = it },
    ) {
        Column(Modifier.verticalScroll(rememberScrollState())) {
            repeat(4) { idx ->
                val resultText = "Suggestion $idx"
                ListItem(
                    headlineContent = { Text(resultText) },
                    supportingContent = { Text("Additional info") },
                    leadingContent = { Icon(Icons.Filled.Star, contentDescription = null) },
                    colors = ListItemDefaults.colors(containerColor = Color.Transparent),
                    modifier =
                        Modifier.clickable {
                                textFieldState.setTextAndPlaceCursorAtEnd(resultText)
                                expanded = false
                            }
                            .fillMaxWidth()
                            .padding(horizontal = 16.dp, vertical = 4.dp)
                )
            }
        }
    }

    LazyColumn(
        contentPadding = PaddingValues(start = 16.dp, top = 72.dp, end = 16.dp, bottom = 16.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp),
        modifier = Modifier.semantics { traversalIndex = 1f },
    ) {
        val list = List(100) { "Text $it" }
        items(count = list.size) {
            Text(
                text = list[it],
                modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
            )
        }
    }
}
Parameters
inputField: @Composable () -> Unit

the input field of this search bar that allows entering a query, typically a SearchBarDefaults.InputField.

expanded: Boolean

whether this search bar is expanded and showing search results.

onExpandedChange: (Boolean) -> Unit

the callback to be invoked when this search bar's expanded state is changed.

modifier: Modifier = Modifier

the Modifier to be applied to this search bar.

shape: Shape = SearchBarDefaults.inputFieldShape

the shape of this search bar when it is not expanded. When expanded, the shape will always be SearchBarDefaults.fullScreenShape.

colors: SearchBarColors = SearchBarDefaults.colors()

SearchBarColors that will be used to resolve the colors used for this search bar in different states. See SearchBarDefaults.colors.

tonalElevation: Dp = SearchBarDefaults.TonalElevation

when SearchBarColors.containerColor is ColorScheme.surface, a translucent primary color overlay is applied on top of the container. A higher tonal elevation value will result in a darker color in light theme and lighter color in dark theme. See also: Surface.

shadowElevation: Dp = SearchBarDefaults.ShadowElevation

the elevation for the shadow below this search bar

windowInsets: WindowInsets = SearchBarDefaults.windowInsets

the window insets that this search bar will respect

content: @Composable ColumnScope.() -> Unit

the content of this search bar to display search results below the inputField.

@ExperimentalMaterial3Api
@Composable
fun SearchBar(
    query: String,
    onQueryChange: (String) -> Unit,
    onSearch: (String) -> Unit,
    active: Boolean,
    onActiveChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    placeholder: (@Composable () -> Unit)? = null,
    leadingIcon: (@Composable () -> Unit)? = null,
    trailingIcon: (@Composable () -> Unit)? = null,
    shape: Shape = SearchBarDefaults.inputFieldShape,
    colors: SearchBarColors = SearchBarDefaults.colors(),
    tonalElevation: Dp = SearchBarDefaults.TonalElevation,
    shadowElevation: Dp = SearchBarDefaults.ShadowElevation,
    windowInsets: WindowInsets = SearchBarDefaults.windowInsets,
    interactionSource: MutableInteractionSource? = null,
    content: @Composable ColumnScope.() -> Unit
): Unit

SecondaryScrollableTabRow

@ExperimentalMaterial3Api
@Composable
fun SecondaryScrollableTabRow(
    selectedTabIndex: Int,
    modifier: Modifier = Modifier,
    scrollState: ScrollState = rememberScrollState(),
    containerColor: Color = TabRowDefaults.secondaryContainerColor,
    contentColor: Color = TabRowDefaults.secondaryContentColor,
    edgePadding: Dp = TabRowDefaults.ScrollableTabRowEdgeStartPadding,
    indicator: @Composable TabIndicatorScope.() -> Unit = @Composable { TabRowDefaults.SecondaryIndicator( Modifier.tabIndicatorOffset(selectedTabIndex, matchContentSize = false) ) },
    divider: @Composable () -> Unit = @Composable { HorizontalDivider() },
    tabs: @Composable () -> Unit
): Unit

Material Design Scrollable Secondary tabs

Material Design scrollable tabs.

Secondary tabs are used within a content area to further separate related content and establish hierarchy. When a set of tabs cannot fit on screen, use scrollable tabs. Scrollable tabs can use longer text labels and a larger number of tabs. They are best used for browsing on touch interfaces.

A scrollable tab row contains a row of Tabs, and displays an indicator underneath the currently selected tab. A scrollable tab row places its tabs offset from the starting edge, and allows scrolling to tabs that are placed off screen. For a fixed tab row that does not allow scrolling, and evenly places its tabs, see SecondaryTabRow.

Parameters
selectedTabIndex: Int

the index of the currently selected tab

modifier: Modifier = Modifier

the Modifier to be applied to this tab row

scrollState: ScrollState = rememberScrollState()

the ScrollState of this tab row

containerColor: Color = TabRowDefaults.secondaryContainerColor

the color used for the background of this tab row. Use Color.Transparent to have no color.

contentColor: Color = TabRowDefaults.secondaryContentColor

the preferred color for content inside this tab row. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

edgePadding: Dp = TabRowDefaults.ScrollableTabRowEdgeStartPadding

the padding between the starting and ending edge of the scrollable tab row, and the tabs inside the row. This padding helps inform the user that this tab row can be scrolled, unlike a TabRow.

indicator: @Composable TabIndicatorScope.() -> Unit = @Composable { TabRowDefaults.SecondaryIndicator( Modifier.tabIndicatorOffset(selectedTabIndex, matchContentSize = false) ) }

the indicator that represents which tab is currently selected. By default this will be a TabRowDefaults.SecondaryIndicator, using a TabRowDefaults.tabIndicatorOffset modifier to animate its position. Note that this indicator will be forced to fill up the entire tab row, so you should use TabRowDefaults.tabIndicatorOffset or similar to animate the actual drawn indicator inside this space, and provide an offset from the start.

divider: @Composable () -> Unit = @Composable { HorizontalDivider() }

the divider displayed at the bottom of the tab row. This provides a layer of separation between the tab row and the content displayed underneath.

tabs: @Composable () -> Unit

the tabs inside this tab row. Typically this will be multiple Tabs. Each element inside this lambda will be measured and placed evenly across the row, each taking up equal space.

SecondaryTabRow

@ExperimentalMaterial3Api
@Composable
fun SecondaryTabRow(
    selectedTabIndex: Int,
    modifier: Modifier = Modifier,
    containerColor: Color = TabRowDefaults.secondaryContainerColor,
    contentColor: Color = TabRowDefaults.secondaryContentColor,
    indicator: @Composable TabIndicatorScope.() -> Unit = @Composable { TabRowDefaults.SecondaryIndicator( Modifier.tabIndicatorOffset(selectedTabIndex, matchContentSize = false) ) },
    divider: @Composable () -> Unit = @Composable { HorizontalDivider() },
    tabs: @Composable () -> Unit
): Unit

Material Design Fixed Secondary tabs

Secondary tabs are used within a content area to further separate related content and establish hierarchy. Fixed tabs display all tabs in a set simultaneously. To navigate between fixed tabs, tap an individual tab, or swipe left or right in the content area.

A TabRow contains a row of Tabs, and displays an indicator underneath the currently selected tab. A Fixed TabRow places its tabs evenly spaced along the entire row, with each tab taking up an equal amount of space. See SecondaryScrollableTabRow for a tab row that does not enforce equal size, and allows scrolling to tabs that do not fit on screen.

A simple example with text tabs looks like:

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SecondaryTabRow
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow

var state by remember { mutableStateOf(0) }
val titles = listOf("Tab 1", "Tab 2", "Tab 3 with lots of text")
Column {
    SecondaryTabRow(selectedTabIndex = state) {
        titles.forEachIndexed { index, title ->
            Tab(
                selected = state == index,
                onClick = { state = index },
                text = { Text(text = title, maxLines = 2, overflow = TextOverflow.Ellipsis) }
            )
        }
    }
    Text(
        modifier = Modifier.align(Alignment.CenterHorizontally),
        text = "Secondary tab ${state + 1} selected",
        style = MaterialTheme.typography.bodyLarge
    )
}
Parameters
selectedTabIndex: Int

the index of the currently selected tab

modifier: Modifier = Modifier

the Modifier to be applied to this tab row

containerColor: Color = TabRowDefaults.secondaryContainerColor

the color used for the background of this tab row. Use Color.Transparent to have no color.

contentColor: Color = TabRowDefaults.secondaryContentColor

the preferred color for content inside this tab row. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

indicator: @Composable TabIndicatorScope.() -> Unit = @Composable { TabRowDefaults.SecondaryIndicator( Modifier.tabIndicatorOffset(selectedTabIndex, matchContentSize = false) ) }

the indicator that represents which tab is currently selected. By default this will be a TabRowDefaults.SecondaryIndicator, using a TabRowDefaults.tabIndicatorOffset modifier to animate its position. Note that this indicator will be forced to fill up the entire tab row, so you should use TabRowDefaults.tabIndicatorOffset or similar to animate the actual drawn indicator inside this space, and provide an offset from the start.

divider: @Composable () -> Unit = @Composable { HorizontalDivider() }

the divider displayed at the bottom of the tab row. This provides a layer of separation between the tab row and the content displayed underneath.

tabs: @Composable () -> Unit

the tabs inside this tab row. Typically this will be multiple Tabs. Each element inside this lambda will be measured and placed evenly across the row, each taking up equal space.

SecureTextField

@Composable
fun SecureTextField(
    state: TextFieldState,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    textStyle: TextStyle = LocalTextStyle.current,
    labelPosition: TextFieldLabelPosition = TextFieldLabelPosition.Attached(),
    label: (@Composable TextFieldLabelScope.() -> Unit)? = null,
    placeholder: (@Composable () -> Unit)? = null,
    leadingIcon: (@Composable () -> Unit)? = null,
    trailingIcon: (@Composable () -> Unit)? = null,
    prefix: (@Composable () -> Unit)? = null,
    suffix: (@Composable () -> Unit)? = null,
    supportingText: (@Composable () -> Unit)? = null,
    isError: Boolean = false,
    inputTransformation: InputTransformation? = null,
    textObfuscationMode: TextObfuscationMode = TextObfuscationMode.RevealLastTyped,
    textObfuscationCharacter: Char = DefaultObfuscationCharacter,
    keyboardOptions: KeyboardOptions = SecureTextFieldKeyboardOptions,
    onKeyboardAction: KeyboardActionHandler? = null,
    onTextLayout: (Density.(getResult: () -> TextLayoutResult?) -> Unit)? = null,
    shape: Shape = TextFieldDefaults.shape,
    colors: TextFieldColors = TextFieldDefaults.colors(),
    contentPadding: PaddingValues = if (label == null || labelPosition is TextFieldLabelPosition.Above) { TextFieldDefaults.contentPaddingWithoutLabel() } else { TextFieldDefaults.contentPaddingWithLabel() },
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design filled text field for secure content.

Text fields allow users to enter text into a UI. SecureTextField is specifically designed for password entry fields. It only supports a single line of content and comes with default settings that are appropriate for entering secure content. Additionally, some context menu actions like cut, copy, and drag are disabled for added security.

Filled text fields have more visual emphasis than outlined text fields, making them stand out when surrounded by other content and components. For an outlined version, see OutlinedSecureTextField.

Example of a password text field:

import androidx.compose.foundation.text.input.TextObfuscationMode
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Visibility
import androidx.compose.material.icons.filled.VisibilityOff
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.SecureTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable

var passwordHidden by rememberSaveable { mutableStateOf(true) }
SecureTextField(
    state = rememberTextFieldState(),
    label = { Text("Enter password") },
    textObfuscationMode =
        if (passwordHidden) TextObfuscationMode.RevealLastTyped
        else TextObfuscationMode.Visible,
    trailingIcon = {
        IconButton(onClick = { passwordHidden = !passwordHidden }) {
            val visibilityIcon =
                if (passwordHidden) Icons.Filled.Visibility else Icons.Filled.VisibilityOff
            // Provide localized description for accessibility services
            val description = if (passwordHidden) "Show password" else "Hide password"
            Icon(imageVector = visibilityIcon, contentDescription = description)
        }
    }
)
Parameters
state: TextFieldState

TextFieldState object that holds the internal editing state of the text field.

modifier: Modifier = Modifier

the Modifier to be applied to this text field.

enabled: Boolean = true

controls the enabled state of this text field. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

textStyle: TextStyle = LocalTextStyle.current

the style to be applied to the input text. Defaults to LocalTextStyle.

labelPosition: TextFieldLabelPosition = TextFieldLabelPosition.Attached()

the position of the label. See TextFieldLabelPosition.

label: (@Composable TextFieldLabelScope.() -> Unit)? = null

the optional label to be displayed with this text field. The default text style uses Typography.bodySmall when minimized and Typography.bodyLarge when expanded.

placeholder: (@Composable () -> Unit)? = null

the optional placeholder to be displayed when the input text is empty. The default text style uses Typography.bodyLarge.

leadingIcon: (@Composable () -> Unit)? = null

the optional leading icon to be displayed at the beginning of the text field container.

trailingIcon: (@Composable () -> Unit)? = null

the optional trailing icon to be displayed at the end of the text field container.

prefix: (@Composable () -> Unit)? = null

the optional prefix to be displayed before the input text in the text field.

suffix: (@Composable () -> Unit)? = null

the optional suffix to be displayed after the input text in the text field.

supportingText: (@Composable () -> Unit)? = null

the optional supporting text to be displayed below the text field.

isError: Boolean = false

indicates if the text field's current value is in error. When true, the components of the text field will be displayed in an error color, and an error will be announced to accessibility services.

inputTransformation: InputTransformation? = null

optional InputTransformation that will be used to transform changes to the TextFieldState made by the user. The transformation will be applied to changes made by hardware and software keyboard events, pasting or dropping text, accessibility services, and tests. The transformation will not be applied when changing the state programmatically, or when the transformation is changed. If the transformation is changed on an existing text field, it will be applied to the next user edit. The transformation will not immediately affect the current state.

textObfuscationMode: TextObfuscationMode = TextObfuscationMode.RevealLastTyped

the method used to obscure the input text.

textObfuscationCharacter: Char = DefaultObfuscationCharacter

the character to use while obfuscating the text. It doesn't have an effect when textObfuscationMode is set to TextObfuscationMode.Visible.

keyboardOptions: KeyboardOptions = SecureTextFieldKeyboardOptions

software keyboard options that contains configuration such as KeyboardType and ImeAction. This component by default configures KeyboardOptions for a secure text field by disabling auto correct and setting KeyboardType to KeyboardType.Password.

onKeyboardAction: KeyboardActionHandler? = null

called when the user presses the action button in the input method editor (IME), or by pressing the enter key on a hardware keyboard. By default this parameter is null, and would execute the default behavior for a received IME Action e.g., ImeAction.Done would close the keyboard, ImeAction.Next would switch the focus to the next focusable item on the screen.

onTextLayout: (Density.(getResult: () -> TextLayoutResult?) -> Unit)? = null

Callback that is executed when the text layout becomes queryable. The callback receives a function that returns a TextLayoutResult if the layout can be calculated, or null if it cannot. The function reads the layout result from a snapshot state object, and will invalidate its caller when the layout result changes. A TextLayoutResult object contains paragraph information, size of the text, baselines and other details. Density scope is the one that was used while creating the given text layout.

shape: Shape = TextFieldDefaults.shape

defines the shape of this text field's container.

colors: TextFieldColors = TextFieldDefaults.colors()

TextFieldColors that will be used to resolve the colors used for this text field in different states. See TextFieldDefaults.colors.

contentPadding: PaddingValues = if (label == null || labelPosition is TextFieldLabelPosition.Above) { TextFieldDefaults.contentPaddingWithoutLabel() } else { TextFieldDefaults.contentPaddingWithLabel() }

the padding applied to the inner text field that separates it from the surrounding elements of the text field. Note that the padding values may not be respected if they are incompatible with the text field's size constraints or layout. See TextFieldDefaults.contentPaddingWithLabel and TextFieldDefaults.contentPaddingWithoutLabel.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this text field. You can use this to change the text field's appearance or preview the text field in different states. Note that if null is provided, interactions will still happen internally.

ShortNavigationBar

@ExperimentalMaterial3ExpressiveApi
@Composable
fun ShortNavigationBar(
    modifier: Modifier = Modifier,
    containerColor: Color = ShortNavigationBarDefaults.containerColor,
    contentColor: Color = ShortNavigationBarDefaults.contentColor,
    windowInsets: WindowInsets = ShortNavigationBarDefaults.windowInsets,
    arrangement: ShortNavigationBarArrangement = ShortNavigationBarDefaults.arrangement,
    content: @Composable () -> Unit
): Unit

Material Design short navigation bar.

Short navigation bars offer a persistent and convenient way to switch between primary destinations in an app.

The recommended configuration of the ShortNavigationBar depends on the width size of the screen it's being displayed at:

A simple example of the first configuration looks like this:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Star
import androidx.compose.material.icons.outlined.FavoriteBorder
import androidx.compose.material.icons.outlined.Home
import androidx.compose.material.icons.outlined.StarBorder
import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.ShortNavigationBar
import androidx.compose.material3.ShortNavigationBarItem
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember

var selectedItem by remember { mutableIntStateOf(0) }
val items = listOf("Songs", "Artists", "Playlists")
val selectedIcons = listOf(Icons.Filled.Home, Icons.Filled.Favorite, Icons.Filled.Star)
val unselectedIcons =
    listOf(Icons.Outlined.Home, Icons.Outlined.FavoriteBorder, Icons.Outlined.StarBorder)

ShortNavigationBar {
    items.forEachIndexed { index, item ->
        ShortNavigationBarItem(
            icon = {
                Icon(
                    if (selectedItem == index) selectedIcons[index] else unselectedIcons[index],
                    contentDescription = null
                )
            },
            label = { Text(item) },
            selected = selectedItem == index,
            onClick = { selectedItem = index }
        )
    }
}

And of the second configuration:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Star
import androidx.compose.material.icons.outlined.FavoriteBorder
import androidx.compose.material.icons.outlined.Home
import androidx.compose.material.icons.outlined.StarBorder
import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.NavigationItemIconPosition
import androidx.compose.material3.ShortNavigationBar
import androidx.compose.material3.ShortNavigationBarArrangement
import androidx.compose.material3.ShortNavigationBarItem
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

var selectedItem by remember { mutableIntStateOf(0) }
val items = listOf("Songs", "Artists", "Playlists")
val selectedIcons = listOf(Icons.Filled.Home, Icons.Filled.Favorite, Icons.Filled.Star)
val unselectedIcons =
    listOf(Icons.Outlined.Home, Icons.Outlined.FavoriteBorder, Icons.Outlined.StarBorder)

Column {
    Text(
        "Note: this is configuration is better displayed in medium screen sizes.",
        Modifier.padding(16.dp)
    )

    Spacer(Modifier.height(32.dp))

    ShortNavigationBar(arrangement = ShortNavigationBarArrangement.Centered) {
        items.forEachIndexed { index, item ->
            ShortNavigationBarItem(
                iconPosition = NavigationItemIconPosition.Start,
                icon = {
                    Icon(
                        if (selectedItem == index) selectedIcons[index]
                        else unselectedIcons[index],
                        contentDescription = null
                    )
                },
                label = { Text(item) },
                selected = selectedItem == index,
                onClick = { selectedItem = index }
            )
        }
    }
}

See ShortNavigationBarItem for configurations specific to each item, and not the overall ShortNavigationBar component.

Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this navigation bar

containerColor: Color = ShortNavigationBarDefaults.containerColor

the color used for the background of this navigation bar. Use Color.Transparent to have no color

contentColor: Color = ShortNavigationBarDefaults.contentColor

the color for content inside this navigation bar.

windowInsets: WindowInsets = ShortNavigationBarDefaults.windowInsets

a window insets of the navigation bar

arrangement: ShortNavigationBarArrangement = ShortNavigationBarDefaults.arrangement

the ShortNavigationBarArrangement of this navigation bar

content: @Composable () -> Unit

the content of this navigation bar, typically ShortNavigationBarItems

ShortNavigationBarItem

@ExperimentalMaterial3ExpressiveApi
@Composable
fun ShortNavigationBarItem(
    selected: Boolean,
    onClick: () -> Unit,
    icon: @Composable () -> Unit,
    label: (@Composable () -> Unit)?,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    iconPosition: NavigationItemIconPosition = NavigationItemIconPosition.Top,
    colors: NavigationItemColors = ShortNavigationBarItemDefaults.colors(),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design short navigation bar item.

Short navigation bars offer a persistent and convenient way to switch between primary destinations in an app.

It's recommend for navigation items to always have a text label. An ShortNavigationBarItem always displays labels (if they exist) when selected and unselected.

The ShortNavigationBarItem supports two different icon positions, top and start, which is controlled by the iconPosition param:

  • If the icon position is NavigationItemIconPosition.Top the icon will be displayed above the label. This configuration is recommended for short navigation bars used in small width screens, like a phone in portrait mode.

  • If the icon position is NavigationItemIconPosition.Start the icon will be displayed to the start of the label. This configuration is recommended for short navigation bars used in medium width screens, like a phone in landscape mode.

Parameters
selected: Boolean

whether this item is selected

onClick: () -> Unit

called when this item is clicked

icon: @Composable () -> Unit

icon for this item, typically an Icon

label: (@Composable () -> Unit)?

text label for this item

modifier: Modifier = Modifier

the Modifier to be applied to this item

enabled: Boolean = true

controls the enabled state of this item. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

iconPosition: NavigationItemIconPosition = NavigationItemIconPosition.Top

the NavigationItemIconPosition for the icon

colors: NavigationItemColors = ShortNavigationBarItemDefaults.colors()

NavigationItemColors that will be used to resolve the colors used for this item in different states. See ShortNavigationBarItemDefaults.colors

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this item. You can use this to change the item's appearance or preview the item in different states. Note that if null is provided, interactions will still happen internally.

SingleChoiceSegmentedButtonRow

@Composable
fun SingleChoiceSegmentedButtonRow(
    modifier: Modifier = Modifier,
    space: Dp = SegmentedButtonDefaults.BorderWidth,
    content: @Composable SingleChoiceSegmentedButtonRowScope.() -> Unit
): Unit

Material Segmented Button.

A Layout to correctly position and size SegmentedButtons in a Row. It handles overlapping items so that strokes of the item are correctly on top of each other. SingleChoiceSegmentedButtonRow is used when the selection only allows one value, for correct semantics.

import androidx.compose.foundation.layout.size
import androidx.compose.material3.SegmentedButton
import androidx.compose.material3.SegmentedButtonDefaults
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var selectedIndex by remember { mutableStateOf(0) }
val options = listOf("Day", "Month", "Week")
SingleChoiceSegmentedButtonRow {
    options.forEachIndexed { index, label ->
        SegmentedButton(
            shape = SegmentedButtonDefaults.itemShape(index = index, count = options.size),
            onClick = { selectedIndex = index },
            selected = index == selectedIndex
        ) {
            Text(label)
        }
    }
}
Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this row

space: Dp = SegmentedButtonDefaults.BorderWidth

the dimension of the overlap between buttons. Should be equal to the stroke width used on the items.

content: @Composable SingleChoiceSegmentedButtonRowScope.() -> Unit

the content of this Segmented Button Row, typically a sequence of SegmentedButtons

@Composable
@ExperimentalMaterial3Api
fun Slider(
    state: SliderState,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: SliderColors = SliderDefaults.colors(),
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    thumb: @Composable (SliderState) -> Unit = { SliderDefaults.Thumb( interactionSource = interactionSource, colors = colors, enabled = enabled ) },
    track: @Composable (SliderState) -> Unit = { sliderState -> SliderDefaults.Track(colors = colors, enabled = enabled, sliderState = sliderState) }
): Unit

Material Design slider.

Sliders allow users to make selections from a range of values.

Sliders reflect a range of values along a bar, from which users may select a single value. They are ideal for adjusting settings such as volume, brightness, or applying image filters.

Sliders image

Use continuous sliders to allow users to make meaningful selections that don’t require a specific value:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

var sliderPosition by remember { mutableStateOf(0f) }
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    Text(text = "%.2f".format(sliderPosition))
    Slider(
        modifier = Modifier.semantics { contentDescription = "Localized Description" },
        value = sliderPosition,
        onValueChange = { sliderPosition = it }
    )
}

You can allow the user to choose only between predefined set of values by specifying the amount of steps between min and max values:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

var sliderPosition by remember { mutableStateOf(0f) }
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    Text(text = sliderPosition.roundToInt().toString())
    Slider(
        modifier = Modifier.semantics { contentDescription = "Localized Description" },
        value = sliderPosition,
        onValueChange = { sliderPosition = it },
        valueRange = 0f..100f,
        onValueChangeFinished = {
            // launch some business logic update with the state you hold
            // viewModel.updateSelectedSliderValue(sliderPosition)
        },
        // Only allow multiples of 10. Excluding the endpoints of `valueRange`,
        // there are 9 steps (10, 20, ..., 90).
        steps = 9
    )
}

Slider using a custom thumb:

import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.Label
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

var sliderPosition by remember { mutableStateOf(0f) }
val interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    Slider(
        modifier = Modifier.semantics { contentDescription = "Localized Description" },
        value = sliderPosition,
        onValueChange = { sliderPosition = it },
        valueRange = 0f..100f,
        interactionSource = interactionSource,
        onValueChangeFinished = {
            // launch some business logic update with the state you hold
            // viewModel.updateSelectedSliderValue(sliderPosition)
        },
        thumb = {
            Label(
                label = {
                    PlainTooltip(modifier = Modifier.sizeIn(45.dp, 25.dp).wrapContentWidth()) {
                        Text("%.2f".format(sliderPosition))
                    }
                },
                interactionSource = interactionSource
            ) {
                Icon(
                    imageVector = Icons.Filled.Favorite,
                    contentDescription = null,
                    modifier = Modifier.size(ButtonDefaults.IconSize),
                    tint = Color.Red
                )
            }
        }
    )
}

Slider using custom track and thumb:

import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Slider
import androidx.compose.material3.SliderDefaults
import androidx.compose.material3.SliderState
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

val sliderState = remember {
    SliderState(
        valueRange = 0f..100f,
        onValueChangeFinished = {
            // launch some business logic update with the state you hold
            // viewModel.updateSelectedSliderValue(sliderPosition)
        }
    )
}
val interactionSource = remember { MutableInteractionSource() }
val colors = SliderDefaults.colors(thumbColor = Color.Red, activeTrackColor = Color.Red)
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    Text(text = "%.2f".format(sliderState.value))
    Slider(
        state = sliderState,
        modifier = Modifier.semantics { contentDescription = "Localized Description" },
        interactionSource = interactionSource,
        thumb = {
            SliderDefaults.Thumb(interactionSource = interactionSource, colors = colors)
        },
        track = { SliderDefaults.Track(colors = colors, sliderState = sliderState) }
    )
}
Parameters
state: SliderState

SliderState which contains the slider's current value.

modifier: Modifier = Modifier

the Modifier to be applied to this slider

enabled: Boolean = true

controls the enabled state of this slider. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

colors: SliderColors = SliderDefaults.colors()

SliderColors that will be used to resolve the colors used for this slider in different states. See SliderDefaults.colors.

interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }

the MutableInteractionSource representing the stream of Interactions for this slider. You can create and pass in your own remembered instance to observe Interactions and customize the appearance / behavior of this slider in different states.

thumb: @Composable (SliderState) -> Unit = { SliderDefaults.Thumb( interactionSource = interactionSource, colors = colors, enabled = enabled ) }

the thumb to be displayed on the slider, it is placed on top of the track. The lambda receives a SliderState which is used to obtain the current active track.

track: @Composable (SliderState) -> Unit = { sliderState -> SliderDefaults.Track(colors = colors, enabled = enabled, sliderState = sliderState) }

the track to be displayed on the slider, it is placed underneath the thumb. The lambda receives a SliderState which is used to obtain the current active track.

@Composable
fun Slider(
    value: Float,
    onValueChange: (Float) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    valueRange: ClosedFloatingPointRange<Float> = 0f..1f,
    steps: @IntRange(from = 0) Int = 0,
    onValueChangeFinished: (() -> Unit)? = null,
    colors: SliderColors = SliderDefaults.colors(),
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
): Unit

Material Design slider.

Sliders allow users to make selections from a range of values.

It uses SliderDefaults.Thumb and SliderDefaults.Track as the thumb and track.

Sliders reflect a range of values along a bar, from which users may select a single value. They are ideal for adjusting settings such as volume, brightness, or applying image filters.

Sliders image

Use continuous sliders to allow users to make meaningful selections that don’t require a specific value:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

var sliderPosition by remember { mutableStateOf(0f) }
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    Text(text = "%.2f".format(sliderPosition))
    Slider(
        modifier = Modifier.semantics { contentDescription = "Localized Description" },
        value = sliderPosition,
        onValueChange = { sliderPosition = it }
    )
}

You can allow the user to choose only between predefined set of values by specifying the amount of steps between min and max values:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

var sliderPosition by remember { mutableStateOf(0f) }
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    Text(text = sliderPosition.roundToInt().toString())
    Slider(
        modifier = Modifier.semantics { contentDescription = "Localized Description" },
        value = sliderPosition,
        onValueChange = { sliderPosition = it },
        valueRange = 0f..100f,
        onValueChangeFinished = {
            // launch some business logic update with the state you hold
            // viewModel.updateSelectedSliderValue(sliderPosition)
        },
        // Only allow multiples of 10. Excluding the endpoints of `valueRange`,
        // there are 9 steps (10, 20, ..., 90).
        steps = 9
    )
}
Parameters
value: Float

current value of the slider. If outside of valueRange provided, value will be coerced to this range.

onValueChange: (Float) -> Unit

callback in which value should be updated

modifier: Modifier = Modifier

the Modifier to be applied to this slider

enabled: Boolean = true

controls the enabled state of this slider. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

valueRange: ClosedFloatingPointRange<Float> = 0f..1f

range of values that this slider can take. The passed value will be coerced to this range.

steps: @IntRange(from = 0) Int = 0

if positive, specifies the amount of discrete allowable values (in addition to the endpoints of the value range). Step values are evenly distributed across the range. If 0, the slider will behave continuously and allow any value from the range. Must not be negative.

onValueChangeFinished: (() -> Unit)? = null

called when value change has ended. This should not be used to update the slider value (use onValueChange instead), but rather to know when the user has completed selecting a new value by ending a drag or a click.

colors: SliderColors = SliderDefaults.colors()

SliderColors that will be used to resolve the colors used for this slider in different states. See SliderDefaults.colors.

interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }

the MutableInteractionSource representing the stream of Interactions for this slider. You can create and pass in your own remembered instance to observe Interactions and customize the appearance / behavior of this slider in different states.

@Composable
@ExperimentalMaterial3Api
fun Slider(
    value: Float,
    onValueChange: (Float) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    onValueChangeFinished: (() -> Unit)? = null,
    colors: SliderColors = SliderDefaults.colors(),
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    steps: @IntRange(from = 0) Int = 0,
    thumb: @Composable (SliderState) -> Unit = { SliderDefaults.Thumb( interactionSource = interactionSource, colors = colors, enabled = enabled ) },
    track: @Composable (SliderState) -> Unit = { sliderState -> SliderDefaults.Track(colors = colors, enabled = enabled, sliderState = sliderState) },
    valueRange: ClosedFloatingPointRange<Float> = 0f..1f
): Unit

Material Design slider.

Sliders allow users to make selections from a range of values.

Sliders reflect a range of values along a bar, from which users may select a single value. They are ideal for adjusting settings such as volume, brightness, or applying image filters.

Sliders image

Use continuous sliders to allow users to make meaningful selections that don’t require a specific value:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

var sliderPosition by remember { mutableStateOf(0f) }
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    Text(text = "%.2f".format(sliderPosition))
    Slider(
        modifier = Modifier.semantics { contentDescription = "Localized Description" },
        value = sliderPosition,
        onValueChange = { sliderPosition = it }
    )
}

You can allow the user to choose only between predefined set of values by specifying the amount of steps between min and max values:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

var sliderPosition by remember { mutableStateOf(0f) }
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    Text(text = sliderPosition.roundToInt().toString())
    Slider(
        modifier = Modifier.semantics { contentDescription = "Localized Description" },
        value = sliderPosition,
        onValueChange = { sliderPosition = it },
        valueRange = 0f..100f,
        onValueChangeFinished = {
            // launch some business logic update with the state you hold
            // viewModel.updateSelectedSliderValue(sliderPosition)
        },
        // Only allow multiples of 10. Excluding the endpoints of `valueRange`,
        // there are 9 steps (10, 20, ..., 90).
        steps = 9
    )
}

Slider using a custom thumb:

import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.Label
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

var sliderPosition by remember { mutableStateOf(0f) }
val interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    Slider(
        modifier = Modifier.semantics { contentDescription = "Localized Description" },
        value = sliderPosition,
        onValueChange = { sliderPosition = it },
        valueRange = 0f..100f,
        interactionSource = interactionSource,
        onValueChangeFinished = {
            // launch some business logic update with the state you hold
            // viewModel.updateSelectedSliderValue(sliderPosition)
        },
        thumb = {
            Label(
                label = {
                    PlainTooltip(modifier = Modifier.sizeIn(45.dp, 25.dp).wrapContentWidth()) {
                        Text("%.2f".format(sliderPosition))
                    }
                },
                interactionSource = interactionSource
            ) {
                Icon(
                    imageVector = Icons.Filled.Favorite,
                    contentDescription = null,
                    modifier = Modifier.size(ButtonDefaults.IconSize),
                    tint = Color.Red
                )
            }
        }
    )
}

Slider using custom track and thumb:

import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Slider
import androidx.compose.material3.SliderDefaults
import androidx.compose.material3.SliderState
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp

val sliderState = remember {
    SliderState(
        valueRange = 0f..100f,
        onValueChangeFinished = {
            // launch some business logic update with the state you hold
            // viewModel.updateSelectedSliderValue(sliderPosition)
        }
    )
}
val interactionSource = remember { MutableInteractionSource() }
val colors = SliderDefaults.colors(thumbColor = Color.Red, activeTrackColor = Color.Red)
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
    Text(text = "%.2f".format(sliderState.value))
    Slider(
        state = sliderState,
        modifier = Modifier.semantics { contentDescription = "Localized Description" },
        interactionSource = interactionSource,
        thumb = {
            SliderDefaults.Thumb(interactionSource = interactionSource, colors = colors)
        },
        track = { SliderDefaults.Track(colors = colors, sliderState = sliderState) }
    )
}
Parameters
value: Float

current value of the slider. If outside of valueRange provided, value will be coerced to this range.

onValueChange: (Float) -> Unit

callback in which value should be updated

modifier: Modifier = Modifier

the Modifier to be applied to this slider

enabled: Boolean = true

controls the enabled state of this slider. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

onValueChangeFinished: (() -> Unit)? = null

called when value change has ended. This should not be used to update the slider value (use onValueChange instead), but rather to know when the user has completed selecting a new value by ending a drag or a click.

colors: SliderColors = SliderDefaults.colors()

SliderColors that will be used to resolve the colors used for this slider in different states. See SliderDefaults.colors.

interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }

the MutableInteractionSource representing the stream of Interactions for this slider. You can create and pass in your own remembered instance to observe Interactions and customize the appearance / behavior of this slider in different states.

steps: @IntRange(from = 0) Int = 0

if positive, specifies the amount of discrete allowable values (in addition to the endpoints of the value range). Step values are evenly distributed across the range. If 0, the slider will behave continuously and allow any value from the range. Must not be negative.

thumb: @Composable (SliderState) -> Unit = { SliderDefaults.Thumb( interactionSource = interactionSource, colors = colors, enabled = enabled ) }

the thumb to be displayed on the slider, it is placed on top of the track. The lambda receives a SliderState which is used to obtain the current active track.

track: @Composable (SliderState) -> Unit = { sliderState -> SliderDefaults.Track(colors = colors, enabled = enabled, sliderState = sliderState) }

the track to be displayed on the slider, it is placed underneath the thumb. The lambda receives a SliderState which is used to obtain the current active track.

valueRange: ClosedFloatingPointRange<Float> = 0f..1f

range of values that this slider can take. The passed value will be coerced to this range.

SmallExtendedFloatingActionButton

@ExperimentalMaterial3ExpressiveApi
@Composable
fun SmallExtendedFloatingActionButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    shape: Shape = FloatingActionButtonDefaults.smallExtendedFabShape,
    containerColor: Color = FloatingActionButtonDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable RowScope.() -> Unit
): Unit

Material Design small extended floating action button.

Extended FABs help people take primary actions. They're wider than FABs to accommodate a text label and larger target area.

The other small extended floating action button overload supports a text label and icon.

import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.SmallExtendedFloatingActionButton
import androidx.compose.material3.Text

SmallExtendedFloatingActionButton(onClick = { /* do something */ }) {
    Text(text = "Small Extended FAB")
}
Parameters
onClick: () -> Unit

called when this FAB is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this FAB

shape: Shape = FloatingActionButtonDefaults.smallExtendedFabShape

defines the shape of this FAB's container and shadow (when using elevation)

containerColor: Color = FloatingActionButtonDefaults.containerColor

the color used for the background of this FAB. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this FAB. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation()

FloatingActionButtonElevation used to resolve the elevation for this FAB in different states. This controls the size of the shadow below the FAB. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See also: Surface.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this FAB. You can use this to change the FAB's appearance or preview the FAB in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable RowScope.() -> Unit

the content of this FAB, typically a Text label

SmallExtendedFloatingActionButton

@ExperimentalMaterial3ExpressiveApi
@Composable
fun SmallExtendedFloatingActionButton(
    text: @Composable () -> Unit,
    icon: @Composable () -> Unit,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    expanded: Boolean = true,
    shape: Shape = FloatingActionButtonDefaults.smallExtendedFabShape,
    containerColor: Color = FloatingActionButtonDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design small extended floating action button.

Extended FABs help people take primary actions. They're wider than FABs to accommodate a text label and larger target area.

The other small extended floating action button overload is for FABs without an icon.

Default content description for accessibility is extended from the extended fabs icon. For custom behavior, you can provide your own via Modifier.semantics.

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.SmallExtendedFloatingActionButton
import androidx.compose.material3.Text

SmallExtendedFloatingActionButton(
    onClick = { /* do something */ },
    icon = { Icon(Icons.Filled.Add, "Localized description") },
    text = { Text(text = "Small Extended FAB") },
)
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FabPosition
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SmallExtendedFloatingActionButton
import androidx.compose.material3.Text
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val listState = rememberLazyListState()
// The FAB is initially expanded. Once the first visible item is past the first item we
// collapse the FAB. We use a remembered derived state to minimize unnecessary compositions.
val expandedFab by remember { derivedStateOf { listState.firstVisibleItemIndex == 0 } }
Scaffold(
    floatingActionButton = {
        SmallExtendedFloatingActionButton(
            onClick = { /* do something */ },
            expanded = expandedFab,
            icon = { Icon(Icons.Filled.Add, "Localized Description") },
            text = { Text(text = "Small Extended FAB") },
        )
    },
    floatingActionButtonPosition = FabPosition.End,
) {
    LazyColumn(state = listState, modifier = Modifier.fillMaxSize()) {
        for (index in 0 until 100) {
            item { Text(text = "List item - $index", modifier = Modifier.padding(24.dp)) }
        }
    }
}
Parameters
text: @Composable () -> Unit

label displayed inside this FAB

icon: @Composable () -> Unit

icon for this FAB, typically an Icon

onClick: () -> Unit

called when this FAB is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this FAB

expanded: Boolean = true

controls the expansion state of this FAB. In an expanded state, the FAB will show both the icon and text. In a collapsed state, the FAB will show only the icon.

shape: Shape = FloatingActionButtonDefaults.smallExtendedFabShape

defines the shape of this FAB's container and shadow (when using elevation)

containerColor: Color = FloatingActionButtonDefaults.containerColor

the color used for the background of this FAB. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this FAB. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation()

FloatingActionButtonElevation used to resolve the elevation for this FAB in different states. This controls the size of the shadow below the FAB. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See also: Surface.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this FAB. You can use this to change the FAB's appearance or preview the FAB in different states. Note that if null is provided, interactions will still happen internally.

SmallFloatingActionButton

@Composable
fun SmallFloatingActionButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    shape: Shape = FloatingActionButtonDefaults.smallShape,
    containerColor: Color = FloatingActionButtonDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
    interactionSource: MutableInteractionSource? = null,
    content: @Composable () -> Unit
): Unit

Material Design small floating action button.

The FAB represents the most important action on a screen. It puts key actions within reach.

Small FAB image

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.SmallFloatingActionButton

SmallFloatingActionButton(
    onClick = { /* do something */ },
) {
    Icon(Icons.Filled.Add, contentDescription = "Localized description")
}

FABs can also be shown and hidden with an animation when the main content is scrolled:

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FabPosition
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MediumFloatingActionButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.animateFloatingActionButton
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val listState = rememberLazyListState()
// The FAB is initially shown. Upon scrolling past the first item we hide the FAB by using a
// remembered derived state to minimize unnecessary compositions.
val fabVisible by remember { derivedStateOf { listState.firstVisibleItemIndex == 0 } }

Scaffold(
    floatingActionButton = {
        MediumFloatingActionButton(
            modifier =
                Modifier.animateFloatingActionButton(
                    visible = fabVisible,
                    alignment = Alignment.BottomEnd
                ),
            onClick = { /* do something */ },
        ) {
            Icon(
                Icons.Filled.Add,
                contentDescription = "Localized description",
                modifier = Modifier.size(FloatingActionButtonDefaults.MediumIconSize),
            )
        }
    },
    floatingActionButtonPosition = FabPosition.End,
) {
    LazyColumn(state = listState, modifier = Modifier.fillMaxSize()) {
        for (index in 0 until 100) {
            item { Text(text = "List item - $index", modifier = Modifier.padding(24.dp)) }
        }
    }
}
Parameters
onClick: () -> Unit

called when this FAB is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this FAB

shape: Shape = FloatingActionButtonDefaults.smallShape

defines the shape of this FAB's container and shadow (when using elevation)

containerColor: Color = FloatingActionButtonDefaults.containerColor

the color used for the background of this FAB. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this FAB. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation()

FloatingActionButtonElevation used to resolve the elevation for this FAB in different states. This controls the size of the shadow below the FAB. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See also: Surface.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this FAB. You can use this to change the FAB's appearance or preview the FAB in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable () -> Unit

the content of this FAB, typically an Icon

@Composable
fun Snackbar(
    snackbarData: SnackbarData,
    modifier: Modifier = Modifier,
    actionOnNewLine: Boolean = false,
    shape: Shape = SnackbarDefaults.shape,
    containerColor: Color = SnackbarDefaults.color,
    contentColor: Color = SnackbarDefaults.contentColor,
    actionColor: Color = SnackbarDefaults.actionColor,
    actionContentColor: Color = SnackbarDefaults.actionContentColor,
    dismissActionContentColor: Color = SnackbarDefaults.dismissActionContentColor
): Unit

Material Design snackbar.

Snackbars provide brief messages about app processes at the bottom of the screen.

Snackbar image

Snackbars inform users of a process that an app has performed or will perform. They appear temporarily, towards the bottom of the screen. They shouldn’t interrupt the user experience, and they don’t require user input to disappear.

A Snackbar can contain a single action. "Dismiss" or "cancel" actions are optional.

Snackbars with an action should not timeout or self-dismiss until the user performs another action. Here, moving the keyboard focus indicator to navigate through interactive elements in a page is not considered an action.

This version of snackbar is designed to work with SnackbarData provided by the SnackbarHost, which is usually used inside of the Scaffold.

This components provides only the visuals of the Snackbar. If you need to show a Snackbar with defaults on the screen, use SnackbarHostState.showSnackbar:

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Snackbar
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier

val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
Scaffold(
    snackbarHost = { SnackbarHost(snackbarHostState) },
    floatingActionButton = {
        var clickCount by remember { mutableStateOf(0) }
        ExtendedFloatingActionButton(
            onClick = {
                // show snackbar as a suspend function
                scope.launch { snackbarHostState.showSnackbar("Snackbar # ${++clickCount}") }
            }
        ) {
            Text("Show snackbar")
        }
    },
    content = { innerPadding ->
        Text(
            text = "Body content",
            modifier = Modifier.padding(innerPadding).fillMaxSize().wrapContentSize()
        )
    }
)

If you want to customize appearance of the Snackbar, you can pass your own version as a child of the SnackbarHost to the Scaffold:

import androidx.compose.foundation.border
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Snackbar
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarVisuals
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

class SnackbarVisualsWithError(override val message: String, val isError: Boolean) :
    SnackbarVisuals {
    override val actionLabel: String
        get() = if (isError) "Error" else "OK"

    override val withDismissAction: Boolean
        get() = false

    override val duration: SnackbarDuration
        get() = SnackbarDuration.Indefinite
}

val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
Scaffold(
    snackbarHost = {
        // reuse default SnackbarHost to have default animation and timing handling
        SnackbarHost(snackbarHostState) { data ->
            // custom snackbar with the custom action button color and border
            val isError = (data.visuals as? SnackbarVisualsWithError)?.isError ?: false
            val buttonColor =
                if (isError) {
                    ButtonDefaults.textButtonColors(
                        containerColor = MaterialTheme.colorScheme.errorContainer,
                        contentColor = MaterialTheme.colorScheme.error
                    )
                } else {
                    ButtonDefaults.textButtonColors(
                        contentColor = MaterialTheme.colorScheme.inversePrimary
                    )
                }

            Snackbar(
                modifier =
                    Modifier.border(2.dp, MaterialTheme.colorScheme.secondary).padding(12.dp),
                action = {
                    TextButton(
                        onClick = { if (isError) data.dismiss() else data.performAction() },
                        colors = buttonColor
                    ) {
                        Text(data.visuals.actionLabel ?: "")
                    }
                }
            ) {
                Text(data.visuals.message)
            }
        }
    },
    floatingActionButton = {
        var clickCount by remember { mutableStateOf(0) }
        ExtendedFloatingActionButton(
            onClick = {
                scope.launch {
                    snackbarHostState.showSnackbar(
                        SnackbarVisualsWithError(
                            "Snackbar # ${++clickCount}",
                            isError = clickCount % 2 != 0
                        )
                    )
                }
            }
        ) {
            Text("Show snackbar")
        }
    },
    content = { innerPadding ->
        Text(
            text = "Custom Snackbar Demo",
            modifier = Modifier.padding(innerPadding).fillMaxSize().wrapContentSize()
        )
    }
)

When a SnackbarData.visuals sets the Snackbar's duration as SnackbarDuration.Indefinite, it's recommended to display an additional close affordance action. See SnackbarVisuals.withDismissAction:

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Snackbar
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier

val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
Scaffold(
    snackbarHost = { SnackbarHost(snackbarHostState) },
    floatingActionButton = {
        var clickCount by remember { mutableStateOf(0) }
        ExtendedFloatingActionButton(
            onClick = {
                // show snackbar as a suspend function
                scope.launch {
                    snackbarHostState.showSnackbar(
                        message = "Snackbar # ${++clickCount}",
                        actionLabel = "Action",
                        withDismissAction = true,
                        duration = SnackbarDuration.Indefinite
                    )
                }
            }
        ) {
            Text("Show snackbar")
        }
    },
    content = { innerPadding ->
        Text(
            text = "Body content",
            modifier = Modifier.padding(innerPadding).fillMaxSize().wrapContentSize()
        )
    }
)
Parameters
snackbarData: SnackbarData

data about the current snackbar showing via SnackbarHostState

modifier: Modifier = Modifier

the Modifier to be applied to this snackbar

actionOnNewLine: Boolean = false

whether or not action should be put on a separate line. Recommended for action with long action text.

shape: Shape = SnackbarDefaults.shape

defines the shape of this snackbar's container

containerColor: Color = SnackbarDefaults.color

the color used for the background of this snackbar. Use Color.Transparent to have no color.

contentColor: Color = SnackbarDefaults.contentColor

the preferred color for content inside this snackbar

actionColor: Color = SnackbarDefaults.actionColor

the color of the snackbar's action

actionContentColor: Color = SnackbarDefaults.actionContentColor

the preferred content color for the optional action inside this snackbar. See SnackbarVisuals.actionLabel.

dismissActionContentColor: Color = SnackbarDefaults.dismissActionContentColor

the preferred content color for the optional dismiss action inside this snackbar. See SnackbarVisuals.withDismissAction.

@Composable
fun Snackbar(
    modifier: Modifier = Modifier,
    action: (@Composable () -> Unit)? = null,
    dismissAction: (@Composable () -> Unit)? = null,
    actionOnNewLine: Boolean = false,
    shape: Shape = SnackbarDefaults.shape,
    containerColor: Color = SnackbarDefaults.color,
    contentColor: Color = SnackbarDefaults.contentColor,
    actionContentColor: Color = SnackbarDefaults.actionContentColor,
    dismissActionContentColor: Color = SnackbarDefaults.dismissActionContentColor,
    content: @Composable () -> Unit
): Unit

Material Design snackbar.

Snackbars provide brief messages about app processes at the bottom of the screen.

Snackbar image

Snackbars inform users of a process that an app has performed or will perform. They appear temporarily, towards the bottom of the screen. They shouldn’t interrupt the user experience, and they don’t require user input to disappear.

A Snackbar can contain a single action. "Dismiss" or "cancel" actions are optional.

Snackbars with an action should not timeout or self-dismiss until the user performs another action. Here, moving the keyboard focus indicator to navigate through interactive elements in a page is not considered an action.

This component provides only the visuals of the Snackbar. If you need to show a Snackbar with defaults on the screen, use SnackbarHostState.showSnackbar:

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Snackbar
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier

val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
Scaffold(
    snackbarHost = { SnackbarHost(snackbarHostState) },
    floatingActionButton = {
        var clickCount by remember { mutableStateOf(0) }
        ExtendedFloatingActionButton(
            onClick = {
                // show snackbar as a suspend function
                scope.launch { snackbarHostState.showSnackbar("Snackbar # ${++clickCount}") }
            }
        ) {
            Text("Show snackbar")
        }
    },
    content = { innerPadding ->
        Text(
            text = "Body content",
            modifier = Modifier.padding(innerPadding).fillMaxSize().wrapContentSize()
        )
    }
)

If you want to customize appearance of the Snackbar, you can pass your own version as a child of the SnackbarHost to the Scaffold:

import androidx.compose.foundation.border
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Snackbar
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarVisuals
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

class SnackbarVisualsWithError(override val message: String, val isError: Boolean) :
    SnackbarVisuals {
    override val actionLabel: String
        get() = if (isError) "Error" else "OK"

    override val withDismissAction: Boolean
        get() = false

    override val duration: SnackbarDuration
        get() = SnackbarDuration.Indefinite
}

val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
Scaffold(
    snackbarHost = {
        // reuse default SnackbarHost to have default animation and timing handling
        SnackbarHost(snackbarHostState) { data ->
            // custom snackbar with the custom action button color and border
            val isError = (data.visuals as? SnackbarVisualsWithError)?.isError ?: false
            val buttonColor =
                if (isError) {
                    ButtonDefaults.textButtonColors(
                        containerColor = MaterialTheme.colorScheme.errorContainer,
                        contentColor = MaterialTheme.colorScheme.error
                    )
                } else {
                    ButtonDefaults.textButtonColors(
                        contentColor = MaterialTheme.colorScheme.inversePrimary
                    )
                }

            Snackbar(
                modifier =
                    Modifier.border(2.dp, MaterialTheme.colorScheme.secondary).padding(12.dp),
                action = {
                    TextButton(
                        onClick = { if (isError) data.dismiss() else data.performAction() },
                        colors = buttonColor
                    ) {
                        Text(data.visuals.actionLabel ?: "")
                    }
                }
            ) {
                Text(data.visuals.message)
            }
        }
    },
    floatingActionButton = {
        var clickCount by remember { mutableStateOf(0) }
        ExtendedFloatingActionButton(
            onClick = {
                scope.launch {
                    snackbarHostState.showSnackbar(
                        SnackbarVisualsWithError(
                            "Snackbar # ${++clickCount}",
                            isError = clickCount % 2 != 0
                        )
                    )
                }
            }
        ) {
            Text("Show snackbar")
        }
    },
    content = { innerPadding ->
        Text(
            text = "Custom Snackbar Demo",
            modifier = Modifier.padding(innerPadding).fillMaxSize().wrapContentSize()
        )
    }
)

For a multiline sample following the Material recommended spec of a maximum of 2 lines, see:

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Snackbar
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow

val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
Scaffold(
    snackbarHost = {
        SnackbarHost(snackbarHostState) { data ->
            Snackbar {
                // The Material spec recommends a maximum of 2 lines of text.
                Text(data.visuals.message, maxLines = 2, overflow = TextOverflow.Ellipsis)
            }
        }
    },
    floatingActionButton = {
        ExtendedFloatingActionButton(
            onClick = {
                scope.launch {
                    val longMessage =
                        "Very very very very very very very very very very very very very " +
                            "very very very very very very very very very very very very " +
                            "very very very very very very very very very very long message"
                    snackbarHostState.showSnackbar(longMessage)
                }
            }
        ) {
            Text("Show snackbar")
        }
    },
    content = { innerPadding ->
        Text(
            text = "Multiline Snackbar Demo",
            modifier = Modifier.padding(innerPadding).fillMaxSize().wrapContentSize()
        )
    }
)
Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this snackbar

action: (@Composable () -> Unit)? = null

action / button component to add as an action to the snackbar. Consider using ColorScheme.inversePrimary as the color for the action, if you do not have a predefined color you wish to use instead.

dismissAction: (@Composable () -> Unit)? = null

action / button component to add as an additional close affordance action when a snackbar is non self-dismissive. Consider using ColorScheme.inverseOnSurface as the color for the action, if you do not have a predefined color you wish to use instead.

actionOnNewLine: Boolean = false

whether or not action should be put on a separate line. Recommended for action with long action text.

shape: Shape = SnackbarDefaults.shape

defines the shape of this snackbar's container

containerColor: Color = SnackbarDefaults.color

the color used for the background of this snackbar. Use Color.Transparent to have no color.

contentColor: Color = SnackbarDefaults.contentColor

the preferred color for content inside this snackbar

actionContentColor: Color = SnackbarDefaults.actionContentColor

the preferred content color for the optional action inside this snackbar

dismissActionContentColor: Color = SnackbarDefaults.dismissActionContentColor

the preferred content color for the optional dismissAction inside this snackbar

content: @Composable () -> Unit

content to show information about a process that an app has performed or will perform

SnackbarHost

@Composable
fun SnackbarHost(
    hostState: SnackbarHostState,
    modifier: Modifier = Modifier,
    snackbar: @Composable (SnackbarData) -> Unit = { Snackbar(it) }
): Unit

Host for Snackbars to be used in Scaffold to properly show, hide and dismiss items based on Material specification and the hostState.

This component with default parameters comes build-in with Scaffold, if you need to show a default Snackbar, use SnackbarHostState.showSnackbar.

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Snackbar
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier

val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
Scaffold(
    snackbarHost = { SnackbarHost(snackbarHostState) },
    floatingActionButton = {
        var clickCount by remember { mutableStateOf(0) }
        ExtendedFloatingActionButton(
            onClick = {
                // show snackbar as a suspend function
                scope.launch { snackbarHostState.showSnackbar("Snackbar # ${++clickCount}") }
            }
        ) {
            Text("Show snackbar")
        }
    },
    content = { innerPadding ->
        Text(
            text = "Body content",
            modifier = Modifier.padding(innerPadding).fillMaxSize().wrapContentSize()
        )
    }
)

If you want to customize appearance of the Snackbar, you can pass your own version as a child of the SnackbarHost to the Scaffold:

import androidx.compose.foundation.border
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Snackbar
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarVisuals
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

class SnackbarVisualsWithError(override val message: String, val isError: Boolean) :
    SnackbarVisuals {
    override val actionLabel: String
        get() = if (isError) "Error" else "OK"

    override val withDismissAction: Boolean
        get() = false

    override val duration: SnackbarDuration
        get() = SnackbarDuration.Indefinite
}

val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
Scaffold(
    snackbarHost = {
        // reuse default SnackbarHost to have default animation and timing handling
        SnackbarHost(snackbarHostState) { data ->
            // custom snackbar with the custom action button color and border
            val isError = (data.visuals as? SnackbarVisualsWithError)?.isError ?: false
            val buttonColor =
                if (isError) {
                    ButtonDefaults.textButtonColors(
                        containerColor = MaterialTheme.colorScheme.errorContainer,
                        contentColor = MaterialTheme.colorScheme.error
                    )
                } else {
                    ButtonDefaults.textButtonColors(
                        contentColor = MaterialTheme.colorScheme.inversePrimary
                    )
                }

            Snackbar(
                modifier =
                    Modifier.border(2.dp, MaterialTheme.colorScheme.secondary).padding(12.dp),
                action = {
                    TextButton(
                        onClick = { if (isError) data.dismiss() else data.performAction() },
                        colors = buttonColor
                    ) {
                        Text(data.visuals.actionLabel ?: "")
                    }
                }
            ) {
                Text(data.visuals.message)
            }
        }
    },
    floatingActionButton = {
        var clickCount by remember { mutableStateOf(0) }
        ExtendedFloatingActionButton(
            onClick = {
                scope.launch {
                    snackbarHostState.showSnackbar(
                        SnackbarVisualsWithError(
                            "Snackbar # ${++clickCount}",
                            isError = clickCount % 2 != 0
                        )
                    )
                }
            }
        ) {
            Text("Show snackbar")
        }
    },
    content = { innerPadding ->
        Text(
            text = "Custom Snackbar Demo",
            modifier = Modifier.padding(innerPadding).fillMaxSize().wrapContentSize()
        )
    }
)
Parameters
hostState: SnackbarHostState

state of this component to read and show Snackbars accordingly

modifier: Modifier = Modifier

the Modifier to be applied to this component

snackbar: @Composable (SnackbarData) -> Unit = { Snackbar(it) }

the instance of the Snackbar to be shown at the appropriate time with appearance based on the SnackbarData provided as a param

SplitButtonLayout

@ExperimentalMaterial3ExpressiveApi
@Composable
fun SplitButtonLayout(
    leadingButton: @Composable () -> Unit,
    trailingButton: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    spacing: Dp = SplitButtonDefaults.Spacing
): Unit

A SplitButtonLayout let user define a button group consisting of 2 buttons. The leading button performs a primary action, and the trailing button performs a secondary action that is contextually related to the primary action.

import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.SplitButtonDefaults
import androidx.compose.material3.SplitButtonLayout
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.stateDescription

var checked by remember { mutableStateOf(false) }

SplitButtonLayout(
    leadingButton = {
        SplitButtonDefaults.LeadingButton(
            onClick = { /* Do Nothing */ },
        ) {
            Icon(
                Icons.Filled.Edit,
                modifier = Modifier.size(SplitButtonDefaults.LeadingIconSize),
                contentDescription = "Localized description",
            )
            Spacer(Modifier.size(ButtonDefaults.IconSpacing))
            Text("My Button")
        }
    },
    trailingButton = {
        SplitButtonDefaults.TrailingButton(
            checked = checked,
            onCheckedChange = { checked = it },
            modifier =
                Modifier.semantics {
                    stateDescription = if (checked) "Checked" else "Unchecked"
                    contentDescription = "Toggle Button"
                },
        ) {
            val rotation: Float by
                animateFloatAsState(
                    targetValue = if (checked) 180f else 0f,
                    label = "Trailing Icon Rotation"
                )
            Icon(
                Icons.Filled.KeyboardArrowDown,
                modifier =
                    Modifier.size(SplitButtonDefaults.TrailingIconSize).graphicsLayer {
                        this.rotationZ = rotation
                    },
                contentDescription = "Localized description"
            )
        }
    }
)
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.SplitButtonDefaults
import androidx.compose.material3.SplitButtonLayout
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.stateDescription

var checked by remember { mutableStateOf(false) }

SplitButtonLayout(
    leadingButton = {
        SplitButtonDefaults.TonalLeadingButton(
            onClick = { /* Do Nothing */ },
        ) {
            Icon(
                Icons.Filled.Edit,
                modifier = Modifier.size(SplitButtonDefaults.LeadingIconSize),
                contentDescription = "Localized description",
            )
            Spacer(Modifier.size(ButtonDefaults.IconSpacing))
            Text("My Button")
        }
    },
    trailingButton = {
        SplitButtonDefaults.TonalTrailingButton(
            checked = checked,
            onCheckedChange = { checked = it },
            //                modifier =
            //                    Modifier.semantics {
            //                        stateDescription = if (checked) "Checked" else "Unchecked"
            //                        contentDescription = "Toggle Button"
            //                    },
        ) {
            val rotation: Float by
                animateFloatAsState(
                    targetValue = if (checked) 180f else 0f,
                    label = "Trailing Icon Rotation"
                )
            Icon(
                Icons.Filled.KeyboardArrowDown,
                modifier =
                    Modifier.size(SplitButtonDefaults.TrailingIconSize).graphicsLayer {
                        this.rotationZ = rotation
                    },
                contentDescription = "Localized description"
            )
        }
    }
)
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.SplitButtonDefaults
import androidx.compose.material3.SplitButtonLayout
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.stateDescription

var checked by remember { mutableStateOf(false) }

SplitButtonLayout(
    leadingButton = {
        SplitButtonDefaults.ElevatedLeadingButton(
            onClick = { /* Do Nothing */ },
        ) {
            Icon(
                Icons.Filled.Edit,
                modifier = Modifier.size(SplitButtonDefaults.LeadingIconSize),
                contentDescription = "Localized description",
            )
            Spacer(Modifier.size(ButtonDefaults.IconSpacing))
            Text("My Button")
        }
    },
    trailingButton = {
        SplitButtonDefaults.ElevatedTrailingButton(
            checked = checked,
            onCheckedChange = { checked = it },
            modifier =
                Modifier.semantics {
                    stateDescription = if (checked) "Checked" else "Unchecked"
                    contentDescription = "Toggle Button"
                },
        ) {
            val rotation: Float by
                animateFloatAsState(
                    targetValue = if (checked) 180f else 0f,
                    label = "Trailing Icon Rotation"
                )
            Icon(
                Icons.Filled.KeyboardArrowDown,
                modifier =
                    Modifier.size(SplitButtonDefaults.TrailingIconSize).graphicsLayer {
                        this.rotationZ = rotation
                    },
                contentDescription = "Localized description"
            )
        }
    }
)
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.SplitButtonDefaults
import androidx.compose.material3.SplitButtonLayout
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.stateDescription

var checked by remember { mutableStateOf(false) }

SplitButtonLayout(
    leadingButton = {
        SplitButtonDefaults.OutlinedLeadingButton(
            onClick = { /* Do Nothing */ },
        ) {
            Icon(
                Icons.Filled.Edit,
                modifier = Modifier.size(SplitButtonDefaults.LeadingIconSize),
                contentDescription = "Localized description",
            )
            Spacer(Modifier.size(ButtonDefaults.IconSpacing))
            Text("My Button")
        }
    },
    trailingButton = {
        SplitButtonDefaults.OutlinedTrailingButton(
            checked = checked,
            onCheckedChange = { checked = it },
            modifier =
                Modifier.semantics {
                    stateDescription = if (checked) "Checked" else "Unchecked"
                    contentDescription = "Toggle Button"
                },
        ) {
            val rotation: Float by
                animateFloatAsState(
                    targetValue = if (checked) 180f else 0f,
                    label = "Trailing Icon Rotation"
                )
            Icon(
                Icons.Filled.KeyboardArrowDown,
                modifier =
                    Modifier.size(SplitButtonDefaults.TrailingIconSize).graphicsLayer {
                        this.rotationZ = rotation
                    },
                contentDescription = "Localized description"
            )
        }
    }
)
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.SplitButtonDefaults
import androidx.compose.material3.SplitButtonLayout
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription

SplitButtonLayout(
    leadingButton = {
        SplitButtonDefaults.LeadingButton(
            onClick = { /* Do Nothing */ },
        ) {
            Icon(
                Icons.Filled.Edit,
                modifier = Modifier.size(SplitButtonDefaults.LeadingIconSize),
                contentDescription = "Localized description",
            )
            Spacer(Modifier.size(ButtonDefaults.IconSpacing))
            Text("My Button")
        }
    },
    trailingButton = {
        SplitButtonDefaults.TrailingButton(
            onClick = { /* Do Nothing */ },
        ) {
            Icon(
                Icons.Filled.KeyboardArrowDown,
                modifier = Modifier.size(SplitButtonDefaults.TrailingIconSize),
                contentDescription = "Localized description"
            )
        }
    }
)
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.SplitButtonDefaults
import androidx.compose.material3.SplitButtonLayout
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.semantics.contentDescription

var checked by remember { mutableStateOf(false) }

SplitButtonLayout(
    leadingButton = {
        SplitButtonDefaults.LeadingButton(
            onClick = { /* Do Nothing */ },
        ) {
            Text("My Button")
        }
    },
    trailingButton = {
        SplitButtonDefaults.TrailingButton(
            checked = checked,
            onCheckedChange = { checked = it }
        ) {
            val rotation: Float by
                animateFloatAsState(
                    targetValue = if (checked) 180f else 0f,
                    label = "Trailing Icon Rotation"
                )
            Icon(
                Icons.Filled.KeyboardArrowDown,
                modifier =
                    Modifier.size(SplitButtonDefaults.TrailingIconSize).graphicsLayer {
                        this.rotationZ = rotation
                    },
                contentDescription = "Localized description"
            )
        }
    }
)
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.SplitButtonDefaults
import androidx.compose.material3.SplitButtonLayout
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.semantics.contentDescription

var checked by remember { mutableStateOf(false) }

SplitButtonLayout(
    leadingButton = {
        SplitButtonDefaults.LeadingButton(
            onClick = { /* Do Nothing */ },
        ) {
            Icon(
                Icons.Filled.Edit,
                contentDescription = "Localized description",
                Modifier.size(SplitButtonDefaults.LeadingIconSize)
            )
        }
    },
    trailingButton = {
        SplitButtonDefaults.TrailingButton(
            checked = checked,
            onCheckedChange = { checked = it }
        ) {
            val rotation: Float by
                animateFloatAsState(
                    targetValue = if (checked) 180f else 0f,
                    label = "Trailing Icon Rotation"
                )
            Icon(
                Icons.Filled.KeyboardArrowDown,
                modifier =
                    Modifier.size(SplitButtonDefaults.TrailingIconSize).graphicsLayer {
                        this.rotationZ = rotation
                    },
                contentDescription = "Localized description"
            )
        }
    }
)

Choose the best split button for an action based on the amount of emphasis it needs. The more important an action is, the higher emphasis its button should be.

Use SplitButtonDefaults.LeadingButton and SplitButtonDefaults.TrailingButton to construct a FilledSplitButton. Filled split button is the high-emphasis version of split button. It should be used for emphasizing important or final actions.

Use SplitButtonDefaults.TonalLeadingButton and SplitButtonDefaults.TonalTrailingButton to construct a tonal SplitButton. Tonal split button is the medium-emphasis version of split buttons. It's a middle ground between filled SplitButton and outlined SplitButton

Use SplitButtonDefaults.ElevatedLeadingButton and SplitButtonDefaults.ElevatedTrailingButton to construct a elevated SplitButton. Elevated split buttons are essentially tonal SplitButtons with a shadow. To prevent shadow creep, only use them when absolutely necessary, such as when the button requires visual separation from patterned container.

Use SplitButtonDefaults.OutlinedLeadingButton and SplitButtonDefaults.OutlinedTrailingButton to construct a outlined SplitButton. Outlined split buttons are medium-emphasis buttons. They contain actions that are important, but are not the primary action in an app. Outlined buttons pair well with filled SplitButtons to indicate an alternative, secondary action.

Parameters
leadingButton: @Composable () -> Unit

the leading button. You can specify your own composable or construct a SplitButtonDefaults.LeadingButton

trailingButton: @Composable () -> Unit

the trailing button.You can specify your own composable or construct a SplitButtonDefaults.TrailingButton

modifier: Modifier = Modifier

the Modifier to be applied to this split button.

spacing: Dp = SplitButtonDefaults.Spacing

The spacing between the leadingButton and trailingButton

SuggestionChip

@Composable
fun SuggestionChip(
    onClick: () -> Unit,
    label: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    icon: (@Composable () -> Unit)? = null,
    shape: Shape = SuggestionChipDefaults.shape,
    colors: ChipColors = SuggestionChipDefaults.suggestionChipColors(),
    elevation: ChipElevation? = SuggestionChipDefaults.suggestionChipElevation(),
    border: BorderStroke? = SuggestionChipDefaults.suggestionChipBorder(enabled),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design suggestion chip.

Chips help people enter information, make selections, filter content, or trigger actions. Chips can show multiple interactive elements together in the same area, such as a list of selectable movie times, or a series of email contacts.

Suggestion chips help narrow a user's intent by presenting dynamically generated suggestions, such as possible responses or search filters.

Suggestion chip image

This suggestion chip is applied with a flat style. If you want an elevated style, use the ElevatedSuggestionChip.

Example of a flat SuggestionChip with a trailing icon:

import androidx.compose.material3.SuggestionChip
import androidx.compose.material3.Text

SuggestionChip(onClick = { /* Do something! */ }, label = { Text("Suggestion Chip") })
Parameters
onClick: () -> Unit

called when this chip is clicked

label: @Composable () -> Unit

text label for this chip

modifier: Modifier = Modifier

the Modifier to be applied to this chip

enabled: Boolean = true

controls the enabled state of this chip. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

icon: (@Composable () -> Unit)? = null

optional icon at the start of the chip, preceding the label text

shape: Shape = SuggestionChipDefaults.shape

defines the shape of this chip's container, border (when border is not null), and shadow (when using elevation)

colors: ChipColors = SuggestionChipDefaults.suggestionChipColors()

ChipColors that will be used to resolve the colors used for this chip in different states. See SuggestionChipDefaults.suggestionChipColors.

elevation: ChipElevation? = SuggestionChipDefaults.suggestionChipElevation()

ChipElevation used to resolve the elevation for this chip in different states. This controls the size of the shadow below the chip. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. See SuggestionChipDefaults.suggestionChipElevation.

border: BorderStroke? = SuggestionChipDefaults.suggestionChipBorder(enabled)

the border to draw around the container of this chip. Pass null for no border. See SuggestionChipDefaults.suggestionChipBorder.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this chip. You can use this to change the chip's appearance or preview the chip in different states. Note that if null is provided, interactions will still happen internally.

@Composable
@NonRestartableComposable
fun Surface(
    modifier: Modifier = Modifier,
    shape: Shape = RectangleShape,
    color: Color = MaterialTheme.colorScheme.surface,
    contentColor: Color = contentColorFor(color),
    tonalElevation: Dp = 0.dp,
    shadowElevation: Dp = 0.dp,
    border: BorderStroke? = null,
    content: @Composable () -> Unit
): Unit

Material surface is the central metaphor in material design. Each surface exists at a given elevation, which influences how that piece of surface visually relates to other surfaces and how that surface is modified by tonal variance.

See the other overloads for clickable, selectable, and toggleable surfaces.

The Surface is responsible for:

  1. Clipping: Surface clips its children to the shape specified by shape

  2. Borders: If shape has a border, then it will also be drawn.

  3. Background: Surface fills the shape specified by shape with the color. If color is ColorScheme.surface a color overlay will be applied. The color of the overlay depends on the tonalElevation of this Surface, and the LocalAbsoluteTonalElevation set by any parent surfaces. This ensures that a Surface never appears to have a lower elevation overlay than its ancestors, by summing the elevation of all previous Surfaces.

  4. Content color: Surface uses contentColor to specify a preferred color for the content of this surface - this is used by the Text and Icon components as a default color.

If no contentColor is set, this surface will try and match its background color to a color defined in the theme ColorScheme, and return the corresponding content color. For example, if the color of this surface is ColorScheme.surface, contentColor will be set to ColorScheme.onSurface. If color is not part of the theme palette, contentColor will keep the same value set above this Surface.

To manually retrieve the content color inside a surface, use LocalContentColor.

  1. Blocking touch propagation behind the surface.

Surface sample:

import androidx.compose.material3.Surface
import androidx.compose.material3.Text

Surface { Text("Text on Surface") }
Parameters
modifier: Modifier = Modifier

Modifier to be applied to the layout corresponding to the surface

shape: Shape = RectangleShape

Defines the surface's shape as well its shadow.

color: Color = MaterialTheme.colorScheme.surface

The background color. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(color)

The preferred content color provided by this Surface to its children. Defaults to either the matching content color for color, or if color is not a color from the theme, this will keep the same value set above this Surface.

tonalElevation: Dp = 0.dp

When color is ColorScheme.surface, a higher the elevation will result in a darker color in light theme and lighter color in dark theme.

shadowElevation: Dp = 0.dp

The size of the shadow below the surface. To prevent shadow creep, only apply shadow elevation when absolutely necessary, such as when the surface requires visual separation from a patterned background. Note that It will not affect z index of the Surface. If you want to change the drawing order you can use Modifier.zIndex.

border: BorderStroke? = null

Optional border to draw on top of the surface

content: @Composable () -> Unit

The content to be displayed on this Surface

@Composable
@NonRestartableComposable
fun Surface(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shape: Shape = RectangleShape,
    color: Color = MaterialTheme.colorScheme.surface,
    contentColor: Color = contentColorFor(color),
    tonalElevation: Dp = 0.dp,
    shadowElevation: Dp = 0.dp,
    border: BorderStroke? = null,
    interactionSource: MutableInteractionSource? = null,
    content: @Composable () -> Unit
): Unit

Material surface is the central metaphor in material design. Each surface exists at a given elevation, which influences how that piece of surface visually relates to other surfaces and how that surface is modified by tonal variance.

This version of Surface is responsible for a click handling as well as everything else that a regular Surface does:

This clickable Surface is responsible for:

  1. Clipping: Surface clips its children to the shape specified by shape

  2. Borders: If shape has a border, then it will also be drawn.

  3. Background: Surface fills the shape specified by shape with the color. If color is ColorScheme.surface a color overlay may be applied. The color of the overlay depends on the tonalElevation of this Surface, and the LocalAbsoluteTonalElevation set by any parent surfaces. This ensures that a Surface never appears to have a lower elevation overlay than its ancestors, by summing the elevation of all previous Surfaces.

  4. Content color: Surface uses contentColor to specify a preferred color for the content of this surface - this is used by the Text and Icon components as a default color. If no contentColor is set, this surface will try and match its background color to a color defined in the theme ColorScheme, and return the corresponding content color. For example, if the color of this surface is ColorScheme.surface, contentColor will be set to ColorScheme.onSurface. If color is not part of the theme palette, contentColor will keep the same value set above this Surface.

  5. Click handling. This version of surface will react to the clicks, calling onClick lambda, updating the interactionSource when PressInteraction occurs, and showing ripple indication in response to press events. If you don't need click handling, consider using the Surface function that doesn't require onClick param. If you need to set a custom label for the onClick, apply a Modifier.semantics { onClick(label = "YOUR_LABEL", action = null) } to the Surface.

  6. Semantics for clicks. Just like with Modifier.clickable, clickable version of Surface will produce semantics to indicate that it is clicked. No semantic role is set by default, you may specify one by passing a desired Role with a Modifier.semantics.

To manually retrieve the content color inside a surface, use LocalContentColor.

Clickable surface sample:

import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var count by remember { mutableStateOf(0) }
Surface(
    onClick = { count++ },
) {
    Text("Clickable Surface. Count: $count")
}
Parameters
onClick: () -> Unit

callback to be called when the surface is clicked

modifier: Modifier = Modifier

Modifier to be applied to the layout corresponding to the surface

enabled: Boolean = true

Controls the enabled state of the surface. When false, this surface will not be clickable

shape: Shape = RectangleShape

Defines the surface's shape as well its shadow. A shadow is only displayed if the tonalElevation is greater than zero.

color: Color = MaterialTheme.colorScheme.surface

The background color. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(color)

The preferred content color provided by this Surface to its children. Defaults to either the matching content color for color, or if color is not a color from the theme, this will keep the same value set above this Surface.

tonalElevation: Dp = 0.dp

When color is ColorScheme.surface, a higher the elevation will result in a darker color in light theme and lighter color in dark theme.

shadowElevation: Dp = 0.dp

The size of the shadow below the surface. Note that It will not affect z index of the Surface. If you want to change the drawing order you can use Modifier.zIndex.

border: BorderStroke? = null

Optional border to draw on top of the surface

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this surface. You can use this to change the surface's appearance or preview the surface in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable () -> Unit

The content to be displayed on this Surface

@Composable
@NonRestartableComposable
fun Surface(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shape: Shape = RectangleShape,
    color: Color = MaterialTheme.colorScheme.surface,
    contentColor: Color = contentColorFor(color),
    tonalElevation: Dp = 0.dp,
    shadowElevation: Dp = 0.dp,
    border: BorderStroke? = null,
    interactionSource: MutableInteractionSource? = null,
    content: @Composable () -> Unit
): Unit

Material surface is the central metaphor in material design. Each surface exists at a given elevation, which influences how that piece of surface visually relates to other surfaces and how that surface is modified by tonal variance.

This version of Surface is responsible for a toggling its checked state as well as everything else that a regular Surface does:

This toggleable Surface is responsible for:

  1. Clipping: Surface clips its children to the shape specified by shape

  2. Borders: If shape has a border, then it will also be drawn.

  3. Background: Surface fills the shape specified by shape with the color. If color is ColorScheme.surface a color overlay may be applied. The color of the overlay depends on the tonalElevation of this Surface, and the LocalAbsoluteTonalElevation set by any parent surfaces. This ensures that a Surface never appears to have a lower elevation overlay than its ancestors, by summing the elevation of all previous Surfaces.

  4. Content color: Surface uses contentColor to specify a preferred color for the content of this surface - this is used by the Text and Icon components as a default color. If no contentColor is set, this surface will try and match its background color to a color defined in the theme ColorScheme, and return the corresponding content color. For example, if the color of this surface is ColorScheme.surface, contentColor will be set to ColorScheme.onSurface. If color is not part of the theme palette, contentColor will keep the same value set above this Surface.

  5. Click handling. This version of surface will react to the check toggles, calling onCheckedChange lambda, updating the interactionSource when PressInteraction occurs, and showing ripple indication in response to press events. If you don't need check handling, consider using a Surface function that doesn't require onCheckedChange param.

  6. Semantics for toggle. Just like with Modifier.toggleable, toggleable version of Surface will produce semantics to indicate that it is checked. No semantic role is set by default, you may specify one by passing a desired Role with a Modifier.semantics.

To manually retrieve the content color inside a surface, use LocalContentColor.

Toggleable surface sample:

import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.text.style.TextAlign

var checked by remember { mutableStateOf(false) }
Surface(
    checked = checked,
    onCheckedChange = { checked = !checked },
    color =
        if (checked) {
            MaterialTheme.colorScheme.surfaceVariant
        } else {
            MaterialTheme.colorScheme.surface
        }
) {
    Text(text = if (checked) "ON" else "OFF", textAlign = TextAlign.Center)
}
Parameters
checked: Boolean

whether or not this Surface is toggled on or off

onCheckedChange: (Boolean) -> Unit

callback to be invoked when the toggleable Surface is clicked

modifier: Modifier = Modifier

Modifier to be applied to the layout corresponding to the surface

enabled: Boolean = true

Controls the enabled state of the surface. When false, this surface will not be clickable

shape: Shape = RectangleShape

Defines the surface's shape as well its shadow. A shadow is only displayed if the tonalElevation is greater than zero.

color: Color = MaterialTheme.colorScheme.surface

The background color. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(color)

The preferred content color provided by this Surface to its children. Defaults to either the matching content color for color, or if color is not a color from the theme, this will keep the same value set above this Surface.

tonalElevation: Dp = 0.dp

When color is ColorScheme.surface, a higher the elevation will result in a darker color in light theme and lighter color in dark theme.

shadowElevation: Dp = 0.dp

The size of the shadow below the surface. Note that It will not affect z index of the Surface. If you want to change the drawing order you can use Modifier.zIndex.

border: BorderStroke? = null

Optional border to draw on top of the surface

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this surface. You can use this to change the surface's appearance or preview the surface in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable () -> Unit

The content to be displayed on this Surface

@Composable
@NonRestartableComposable
fun Surface(
    selected: Boolean,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shape: Shape = RectangleShape,
    color: Color = MaterialTheme.colorScheme.surface,
    contentColor: Color = contentColorFor(color),
    tonalElevation: Dp = 0.dp,
    shadowElevation: Dp = 0.dp,
    border: BorderStroke? = null,
    interactionSource: MutableInteractionSource? = null,
    content: @Composable () -> Unit
): Unit

Material surface is the central metaphor in material design. Each surface exists at a given elevation, which influences how that piece of surface visually relates to other surfaces and how that surface is modified by tonal variance.

This version of Surface is responsible for a selection handling as well as everything else that a regular Surface does:

This selectable Surface is responsible for:

  1. Clipping: Surface clips its children to the shape specified by shape

  2. Borders: If shape has a border, then it will also be drawn.

  3. Background: Surface fills the shape specified by shape with the color. If color is ColorScheme.surface a color overlay may be applied. The color of the overlay depends on the tonalElevation of this Surface, and the LocalAbsoluteTonalElevation set by any parent surfaces. This ensures that a Surface never appears to have a lower elevation overlay than its ancestors, by summing the elevation of all previous Surfaces.

  4. Content color: Surface uses contentColor to specify a preferred color for the content of this surface - this is used by the Text and Icon components as a default color. If no contentColor is set, this surface will try and match its background color to a color defined in the theme ColorScheme, and return the corresponding content color. For example, if the color of this surface is ColorScheme.surface, contentColor will be set to ColorScheme.onSurface. If color is not part of the theme palette, contentColor will keep the same value set above this Surface.

  5. Click handling. This version of surface will react to the clicks, calling onClick lambda, updating the interactionSource when PressInteraction occurs, and showing ripple indication in response to press events. If you don't need click handling, consider using the Surface function that doesn't require onClick param.

  6. Semantics for selection. Just like with Modifier.selectable, selectable version of Surface will produce semantics to indicate that it is selected. No semantic role is set by default, you may specify one by passing a desired Role with a Modifier.semantics.

To manually retrieve the content color inside a surface, use LocalContentColor.

Selectable surface sample:

import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.text.style.TextAlign

var selected by remember { mutableStateOf(false) }
Surface(
    selected = selected,
    onClick = { selected = !selected },
) {
    Text(text = if (selected) "Selected" else "Not Selected", textAlign = TextAlign.Center)
}
Parameters
selected: Boolean

whether or not this Surface is selected

onClick: () -> Unit

callback to be called when the surface is clicked

modifier: Modifier = Modifier

Modifier to be applied to the layout corresponding to the surface

enabled: Boolean = true

Controls the enabled state of the surface. When false, this surface will not be clickable

shape: Shape = RectangleShape

Defines the surface's shape as well its shadow. A shadow is only displayed if the tonalElevation is greater than zero.

color: Color = MaterialTheme.colorScheme.surface

The background color. Use Color.Transparent to have no color.

contentColor: Color = contentColorFor(color)

The preferred content color provided by this Surface to its children. Defaults to either the matching content color for color, or if color is not a color from the theme, this will keep the same value set above this Surface.

tonalElevation: Dp = 0.dp

When color is ColorScheme.surface, a higher the elevation will result in a darker color in light theme and lighter color in dark theme.

shadowElevation: Dp = 0.dp

The size of the shadow below the surface. Note that It will not affect z index of the Surface. If you want to change the drawing order you can use Modifier.zIndex.

border: BorderStroke? = null

Optional border to draw on top of the surface

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this surface. You can use this to change the surface's appearance or preview the surface in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable () -> Unit

The content to be displayed on this Surface

SwipeToDismissBox

@Composable
fun SwipeToDismissBox(
    state: SwipeToDismissBoxState,
    backgroundContent: @Composable RowScope.() -> Unit,
    modifier: Modifier = Modifier,
    enableDismissFromStartToEnd: Boolean = true,
    enableDismissFromEndToStart: Boolean = true,
    gesturesEnabled: Boolean = true,
    content: @Composable RowScope.() -> Unit
): Unit

A composable that can be dismissed by swiping left or right.

import androidx.compose.animation.animateColorAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.ListItem
import androidx.compose.material3.OutlinedCard
import androidx.compose.material3.SwipeToDismissBox
import androidx.compose.material3.SwipeToDismissBoxValue
import androidx.compose.material3.Text
import androidx.compose.material3.rememberSwipeToDismissBoxState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape

val dismissState = rememberSwipeToDismissBoxState()
SwipeToDismissBox(
    state = dismissState,
    backgroundContent = {
        val color by
            animateColorAsState(
                when (dismissState.targetValue) {
                    SwipeToDismissBoxValue.Settled -> Color.LightGray
                    SwipeToDismissBoxValue.StartToEnd -> Color.Green
                    SwipeToDismissBoxValue.EndToStart -> Color.Red
                }
            )
        Box(Modifier.fillMaxSize().background(color))
    }
) {
    OutlinedCard(shape = RectangleShape) {
        ListItem(
            headlineContent = { Text("Cupcake") },
            supportingContent = { Text("Swipe me left or right!") }
        )
    }
}
Parameters
state: SwipeToDismissBoxState

The state of this component.

backgroundContent: @Composable RowScope.() -> Unit

A composable that is stacked behind the content and is exposed when the content is swiped. You can/should use the state to have different backgrounds on each side.

modifier: Modifier = Modifier

Optional Modifier for this component.

enableDismissFromStartToEnd: Boolean = true

Whether SwipeToDismissBox can be dismissed from start to end.

enableDismissFromEndToStart: Boolean = true

Whether SwipeToDismissBox can be dismissed from end to start.

gesturesEnabled: Boolean = true

Whether swipe-to-dismiss can be interacted by gestures.

content: @Composable RowScope.() -> Unit

The content that can be dismissed.

@Composable
fun Switch(
    checked: Boolean,
    onCheckedChange: ((Boolean) -> Unit)?,
    modifier: Modifier = Modifier,
    thumbContent: (@Composable () -> Unit)? = null,
    enabled: Boolean = true,
    colors: SwitchColors = SwitchDefaults.colors(),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design Switch.

Switches toggle the state of a single item on or off.

Switch image

import androidx.compose.material.icons.filled.Check
import androidx.compose.material3.Switch
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics

var checked by remember { mutableStateOf(true) }
Switch(
    modifier = Modifier.semantics { contentDescription = "Demo" },
    checked = checked,
    onCheckedChange = { checked = it }
)

Switch can be used with a custom icon via thumbContent parameter

import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material3.Icon
import androidx.compose.material3.Switch
import androidx.compose.material3.SwitchDefaults
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics

var checked by remember { mutableStateOf(true) }

Switch(
    modifier = Modifier.semantics { contentDescription = "Demo with icon" },
    checked = checked,
    onCheckedChange = { checked = it },
    thumbContent = {
        if (checked) {
            // Icon isn't focusable, no need for content description
            Icon(
                imageVector = Icons.Filled.Check,
                contentDescription = null,
                modifier = Modifier.size(SwitchDefaults.IconSize),
            )
        }
    }
)
Parameters
checked: Boolean

whether or not this switch is checked

onCheckedChange: ((Boolean) -> Unit)?

called when this switch is clicked. If null, then this switch will not be interactable, unless something else handles its input events and updates its state.

modifier: Modifier = Modifier

the Modifier to be applied to this switch

thumbContent: (@Composable () -> Unit)? = null

content that will be drawn inside the thumb, expected to measure SwitchDefaults.IconSize

enabled: Boolean = true

controls the enabled state of this switch. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

colors: SwitchColors = SwitchDefaults.colors()

SwitchColors that will be used to resolve the colors used for this switch in different states. See SwitchDefaults.colors.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this switch. You can use this to change the switch's appearance or preview the switch in different states. Note that if null is provided, interactions will still happen internally.

@Composable
fun Tab(
    selected: Boolean,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    selectedContentColor: Color = LocalContentColor.current,
    unselectedContentColor: Color = selectedContentColor,
    interactionSource: MutableInteractionSource? = null,
    content: @Composable ColumnScope.() -> Unit
): Unit

Material Design tab.

Tabs organize content across different screens, data sets, and other interactions.

Tabs image

Generic Tab overload that is not opinionated about content / color. See the other overload for a Tab that has specific slots for text and / or an icon, as well as providing the correct colors for selected / unselected states.

A custom tab using this API may look like:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

Tab(selected, onClick) {
    Column(
        Modifier.padding(10.dp).height(50.dp).fillMaxWidth(),
        verticalArrangement = Arrangement.SpaceBetween
    ) {
        Box(
            Modifier.size(10.dp)
                .align(Alignment.CenterHorizontally)
                .background(
                    color =
                        if (selected) MaterialTheme.colorScheme.primary
                        else MaterialTheme.colorScheme.background
                )
        )
        Text(
            text = title,
            style = MaterialTheme.typography.bodyLarge,
            modifier = Modifier.align(Alignment.CenterHorizontally)
        )
    }
}
Parameters
selected: Boolean

whether this tab is selected or not

onClick: () -> Unit

called when this tab is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this tab

enabled: Boolean = true

controls the enabled state of this tab. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

selectedContentColor: Color = LocalContentColor.current

the color for the content of this tab when selected, and the color of the ripple.

unselectedContentColor: Color = selectedContentColor

the color for the content of this tab when not selected

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this tab. You can use this to change the tab's appearance or preview the tab in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable ColumnScope.() -> Unit

the content of this tab

@Composable
fun Tab(
    selected: Boolean,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    text: (@Composable () -> Unit)? = null,
    icon: (@Composable () -> Unit)? = null,
    selectedContentColor: Color = LocalContentColor.current,
    unselectedContentColor: Color = selectedContentColor,
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design tab.

A default Tab, also known as a Primary Navigation Tab. Tabs organize content across different screens, data sets, and other interactions.

Tabs image

A Tab represents a single page of content using a text label and/or icon. It represents its selected state by tinting the text label and/or image with selectedContentColor.

This should typically be used inside of a TabRow, see the corresponding documentation for example usage.

This Tab has slots for text and/or icon - see the other Tab overload for a generic Tab that is not opinionated about its content.

Parameters
selected: Boolean

whether this tab is selected or not

onClick: () -> Unit

called when this tab is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this tab

enabled: Boolean = true

controls the enabled state of this tab. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

text: (@Composable () -> Unit)? = null

the text label displayed in this tab

icon: (@Composable () -> Unit)? = null

the icon displayed in this tab

selectedContentColor: Color = LocalContentColor.current

the color for the content of this tab when selected, and the color of the ripple.

unselectedContentColor: Color = selectedContentColor

the color for the content of this tab when not selected

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this tab. You can use this to change the tab's appearance or preview the tab in different states. Note that if null is provided, interactions will still happen internally.

See also
LeadingIconTab
@Composable
fun TabRow(
    selectedTabIndex: Int,
    modifier: Modifier = Modifier,
    containerColor: Color = TabRowDefaults.primaryContainerColor,
    contentColor: Color = TabRowDefaults.primaryContentColor,
    indicator: @Composable (tabPositions: List<TabPosition>) -> Unit = @Composable { tabPositions -> if (selectedTabIndex < tabPositions.size) { TabRowDefaults.SecondaryIndicator( Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex]) ) } },
    divider: @Composable () -> Unit = @Composable { HorizontalDivider() },
    tabs: @Composable () -> Unit
): Unit

Material Design tabs

Material Design fixed tabs.

For primary indicator tabs, use PrimaryTabRow. For secondary indicator tabs, use SecondaryTabRow.

Fixed tabs display all tabs in a set simultaneously. They are best for switching between related content quickly, such as between transportation methods in a map. To navigate between fixed tabs, tap an individual tab, or swipe left or right in the content area.

A TabRow contains a row of Tabs, and displays an indicator underneath the currently selected tab. A TabRow places its tabs evenly spaced along the entire row, with each tab taking up an equal amount of space. See ScrollableTabRow for a tab row that does not enforce equal size, and allows scrolling to tabs that do not fit on screen.

A simple example with text tabs looks like:

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.PrimaryTabRow
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow

var state by remember { mutableStateOf(0) }
val titles = listOf("Tab 1", "Tab 2", "Tab 3 with lots of text")
Column {
    PrimaryTabRow(selectedTabIndex = state) {
        titles.forEachIndexed { index, title ->
            Tab(
                selected = state == index,
                onClick = { state = index },
                text = { Text(text = title, maxLines = 2, overflow = TextOverflow.Ellipsis) }
            )
        }
    }
    Text(
        modifier = Modifier.align(Alignment.CenterHorizontally),
        text = "Text tab ${state + 1} selected",
        style = MaterialTheme.typography.bodyLarge
    )
}

You can also provide your own custom tab, such as:

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SecondaryTabRow
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

var state by remember { mutableStateOf(0) }
val titles = listOf("Tab 1", "Tab 2", "Tab 3")
Column {
    SecondaryTabRow(selectedTabIndex = state) {
        titles.forEachIndexed { index, title ->
            FancyTab(title = title, onClick = { state = index }, selected = (index == state))
        }
    }
    Text(
        modifier = Modifier.align(Alignment.CenterHorizontally),
        text = "Fancy tab ${state + 1} selected",
        style = MaterialTheme.typography.bodyLarge
    )
}

Where the custom tab itself could look like:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

Tab(selected, onClick) {
    Column(
        Modifier.padding(10.dp).height(50.dp).fillMaxWidth(),
        verticalArrangement = Arrangement.SpaceBetween
    ) {
        Box(
            Modifier.size(10.dp)
                .align(Alignment.CenterHorizontally)
                .background(
                    color =
                        if (selected) MaterialTheme.colorScheme.primary
                        else MaterialTheme.colorScheme.background
                )
        )
        Text(
            text = title,
            style = MaterialTheme.typography.bodyLarge,
            modifier = Modifier.align(Alignment.CenterHorizontally)
        )
    }
}

As well as customizing the tab, you can also provide a custom indicator, to customize the indicator displayed for a tab. indicator will be placed to fill the entire TabRow, so it should internally take care of sizing and positioning the indicator to match changes to selectedTabIndex.

For example, given an indicator that draws a rounded rectangle near the edges of the Tab:

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Tab
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.unit.dp

// Draws a rounded rectangular with border around the Tab, with a 5.dp padding from the edges
// Color is passed in as a parameter [color]
Box(
    modifier
        .padding(5.dp)
        .fillMaxSize()
        .border(BorderStroke(2.dp, color), RoundedCornerShape(5.dp))
)

We can reuse TabRowDefaults.tabIndicatorOffset and just provide this indicator, as we aren't changing how the size and position of the indicator changes between tabs:

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SecondaryTabRow
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

var state by remember { mutableStateOf(0) }
val titles = listOf("Tab 1", "Tab 2", "Tab 3")

Column {
    SecondaryTabRow(
        selectedTabIndex = state,
        indicator = {
            FancyIndicator(
                MaterialTheme.colorScheme.primary,
                Modifier.tabIndicatorOffset(state)
            )
        }
    ) {
        titles.forEachIndexed { index, title ->
            Tab(selected = state == index, onClick = { state = index }, text = { Text(title) })
        }
    }
    Text(
        modifier = Modifier.align(Alignment.CenterHorizontally),
        text = "Fancy indicator tab ${state + 1} selected",
        style = MaterialTheme.typography.bodyLarge
    )
}

You may also want to use a custom transition, to allow you to dynamically change the appearance of the indicator as it animates between tabs, such as changing its color or size. indicator is stacked on top of the entire TabRow, so you just need to provide a custom transition that animates the offset of the indicator from the start of the TabRow. For example, take the following example that uses a transition to animate the offset, width, and color of the same FancyIndicator from before, also adding a physics based 'spring' effect to the indicator in the direction of motion:

import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.AnimationVector1D
import androidx.compose.animation.core.VectorConverter
import androidx.compose.animation.core.spring
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Tab
import androidx.compose.material3.TabPosition
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.layout.Measurable
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp

val colors =
    listOf(
        MaterialTheme.colorScheme.primary,
        MaterialTheme.colorScheme.secondary,
        MaterialTheme.colorScheme.tertiary,
    )
var startAnimatable by remember { mutableStateOf<Animatable<Dp, AnimationVector1D>?>(null) }
var endAnimatable by remember { mutableStateOf<Animatable<Dp, AnimationVector1D>?>(null) }
val coroutineScope = rememberCoroutineScope()
val indicatorColor: Color by animateColorAsState(colors[index % colors.size], label = "")

Box(
    Modifier.tabIndicatorLayout {
            measurable: Measurable,
            constraints: Constraints,
            tabPositions: List<TabPosition> ->
            val newStart = tabPositions[index].left
            val newEnd = tabPositions[index].right
            val startAnim =
                startAnimatable
                    ?: Animatable(newStart, Dp.VectorConverter).also { startAnimatable = it }

            val endAnim =
                endAnimatable
                    ?: Animatable(newEnd, Dp.VectorConverter).also { endAnimatable = it }

            if (endAnim.targetValue != newEnd) {
                coroutineScope.launch {
                    endAnim.animateTo(
                        newEnd,
                        animationSpec =
                            if (endAnim.targetValue < newEnd) {
                                spring(dampingRatio = 1f, stiffness = 1000f)
                            } else {
                                spring(dampingRatio = 1f, stiffness = 50f)
                            }
                    )
                }
            }

            if (startAnim.targetValue != newStart) {
                coroutineScope.launch {
                    startAnim.animateTo(
                        newStart,
                        animationSpec =
                            // Handle directionality here, if we are moving to the right, we
                            // want the right side of the indicator to move faster, if we are
                            // moving to the left, we want the left side to move faster.
                            if (startAnim.targetValue < newStart) {
                                spring(dampingRatio = 1f, stiffness = 50f)
                            } else {
                                spring(dampingRatio = 1f, stiffness = 1000f)
                            }
                    )
                }
            }

            val indicatorEnd = endAnim.value.roundToPx()
            val indicatorStart = startAnim.value.roundToPx()

            // Apply an offset from the start to correctly position the indicator around the tab
            val placeable =
                measurable.measure(
                    constraints.copy(
                        maxWidth = indicatorEnd - indicatorStart,
                        minWidth = indicatorEnd - indicatorStart,
                    )
                )
            layout(constraints.maxWidth, constraints.maxHeight) {
                placeable.place(indicatorStart, 0)
            }
        }
        .padding(5.dp)
        .fillMaxSize()
        .drawWithContent {
            drawRoundRect(
                color = indicatorColor,
                cornerRadius = CornerRadius(5.dp.toPx()),
                style = Stroke(width = 2.dp.toPx())
            )
        }
)

We can now just pass this indicator directly to TabRow:

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SecondaryTabRow
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

var state by remember { mutableStateOf(0) }
val titles = listOf("Tab 1", "Tab 2", "Tab 3")

Column {
    SecondaryTabRow(
        selectedTabIndex = state,
        indicator = { FancyAnimatedIndicatorWithModifier(state) }
    ) {
        titles.forEachIndexed { index, title ->
            Tab(selected = state == index, onClick = { state = index }, text = { Text(title) })
        }
    }
    Text(
        modifier = Modifier.align(Alignment.CenterHorizontally),
        text = "Fancy transition tab ${state + 1} selected",
        style = MaterialTheme.typography.bodyLarge
    )
}
Parameters
selectedTabIndex: Int

the index of the currently selected tab

modifier: Modifier = Modifier

the Modifier to be applied to this tab row

containerColor: Color = TabRowDefaults.primaryContainerColor

the color used for the background of this tab row. Use Color.Transparent to have no color.

contentColor: Color = TabRowDefaults.primaryContentColor

the preferred color for content inside this tab row. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

indicator: @Composable (tabPositions: List<TabPosition>) -> Unit = @Composable { tabPositions -> if (selectedTabIndex < tabPositions.size) { TabRowDefaults.SecondaryIndicator( Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex]) ) } }

the indicator that represents which tab is currently selected. By default this will be a TabRowDefaults.SecondaryIndicator, using a TabRowDefaults.tabIndicatorOffset modifier to animate its position. Note that this indicator will be forced to fill up the entire tab row, so you should use TabRowDefaults.tabIndicatorOffset or similar to animate the actual drawn indicator inside this space, and provide an offset from the start.

divider: @Composable () -> Unit = @Composable { HorizontalDivider() }

the divider displayed at the bottom of the tab row. This provides a layer of separation between the tab row and the content displayed underneath.

tabs: @Composable () -> Unit

the tabs inside this tab row. Typically this will be multiple Tabs. Each element inside this lambda will be measured and placed evenly across the row, each taking up equal space.

@Composable
fun Text(
    text: String,
    modifier: Modifier = Modifier,
    color: Color = Color.Unspecified,
    fontSize: TextUnit = TextUnit.Unspecified,
    fontStyle: FontStyle? = null,
    fontWeight: FontWeight? = null,
    fontFamily: FontFamily? = null,
    letterSpacing: TextUnit = TextUnit.Unspecified,
    textDecoration: TextDecoration? = null,
    textAlign: TextAlign? = null,
    lineHeight: TextUnit = TextUnit.Unspecified,
    overflow: TextOverflow = TextOverflow.Clip,
    softWrap: Boolean = true,
    maxLines: Int = Int.MAX_VALUE,
    minLines: Int = 1,
    onTextLayout: ((TextLayoutResult) -> Unit)? = null,
    style: TextStyle = LocalTextStyle.current
): Unit

High level element that displays text and provides semantics / accessibility information.

The default style uses the LocalTextStyle provided by the MaterialTheme / components. If you are setting your own style, you may want to consider first retrieving LocalTextStyle, and using TextStyle.copy to keep any theme defined attributes, only modifying the specific attributes you want to override.

For ease of use, commonly used parameters from TextStyle are also present here. The order of precedence is as follows:

  • If a parameter is explicitly set here (i.e, it is not null or TextUnit.Unspecified), then this parameter will always be used.

  • If a parameter is not set, (null or TextUnit.Unspecified), then the corresponding value from style will be used instead.

Additionally, for color, if color is not set, and style does not have a color, then LocalContentColor will be used.

Parameters
text: String

the text to be displayed

modifier: Modifier = Modifier

the Modifier to be applied to this layout node

color: Color = Color.Unspecified

Color to apply to the text. If Color.Unspecified, and style has no color set, this will be LocalContentColor.

fontSize: TextUnit = TextUnit.Unspecified

the size of glyphs to use when painting the text. See TextStyle.fontSize.

fontStyle: FontStyle? = null

the typeface variant to use when drawing the letters (e.g., italic). See TextStyle.fontStyle.

fontWeight: FontWeight? = null

the typeface thickness to use when painting the text (e.g., FontWeight.Bold).

fontFamily: FontFamily? = null

the font family to be used when rendering the text. See TextStyle.fontFamily.

letterSpacing: TextUnit = TextUnit.Unspecified

the amount of space to add between each letter. See TextStyle.letterSpacing.

textDecoration: TextDecoration? = null

the decorations to paint on the text (e.g., an underline). See TextStyle.textDecoration.

textAlign: TextAlign? = null

the alignment of the text within the lines of the paragraph. See TextStyle.textAlign.

lineHeight: TextUnit = TextUnit.Unspecified

line height for the Paragraph in TextUnit unit, e.g. SP or EM. See TextStyle.lineHeight.

overflow: TextOverflow = TextOverflow.Clip

how visual overflow should be handled.

softWrap: Boolean = true

whether the text should break at soft line breaks. If false, the glyphs in the text will be positioned as if there was unlimited horizontal space. If softWrap is false, overflow and TextAlign may have unexpected effects.

maxLines: Int = Int.MAX_VALUE

An optional maximum number of lines for the text to span, wrapping if necessary. If the text exceeds the given number of lines, it will be truncated according to overflow and softWrap. It is required that 1 <= minLines<= maxLines.

minLines: Int = 1

The minimum height in terms of minimum number of visible lines. It is required that 1 <= minLines<= maxLines.

onTextLayout: ((TextLayoutResult) -> Unit)? = null

callback that is executed when a new text layout is calculated. A TextLayoutResult object that callback provides contains paragraph information, size of the text, baselines and other details. The callback can be used to add additional decoration or functionality to the text. For example, to draw selection around the text.

style: TextStyle = LocalTextStyle.current

style configuration for the text such as color, font, line height etc.

@Composable
fun Text(
    text: AnnotatedString,
    modifier: Modifier = Modifier,
    color: Color = Color.Unspecified,
    fontSize: TextUnit = TextUnit.Unspecified,
    fontStyle: FontStyle? = null,
    fontWeight: FontWeight? = null,
    fontFamily: FontFamily? = null,
    letterSpacing: TextUnit = TextUnit.Unspecified,
    textDecoration: TextDecoration? = null,
    textAlign: TextAlign? = null,
    lineHeight: TextUnit = TextUnit.Unspecified,
    overflow: TextOverflow = TextOverflow.Clip,
    softWrap: Boolean = true,
    maxLines: Int = Int.MAX_VALUE,
    minLines: Int = 1,
    inlineContent: Map<StringInlineTextContent> = mapOf(),
    onTextLayout: (TextLayoutResult) -> Unit = {},
    style: TextStyle = LocalTextStyle.current
): Unit

High level element that displays text and provides semantics / accessibility information.

The default style uses the LocalTextStyle provided by the MaterialTheme / components. If you are setting your own style, you may want to consider first retrieving LocalTextStyle, and using TextStyle.copy to keep any theme defined attributes, only modifying the specific attributes you want to override.

For ease of use, commonly used parameters from TextStyle are also present here. The order of precedence is as follows:

  • If a parameter is explicitly set here (i.e, it is not null or TextUnit.Unspecified), then this parameter will always be used.

  • If a parameter is not set, (null or TextUnit.Unspecified), then the corresponding value from style will be used instead.

Additionally, for color, if color is not set, and style does not have a color, then LocalContentColor will be used.

See an example of displaying text with links where links apply the styling from the theme:

import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.ui.text.LinkAnnotation
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.TextLinkStyles
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.withLink

val url = "https://developer.android.com/jetpack/compose"

val linkColor = MaterialTheme.colorScheme.primary
val linkStyle = SpanStyle(color = linkColor, textDecoration = TextDecoration.Underline)

val annotatedString = buildAnnotatedString {
    append("Build better apps faster with ")
    withLink(LinkAnnotation.Url(url = url, styles = TextLinkStyles(style = linkStyle))) {
        append("Jetpack Compose")
    }
}
// Note that if your string is defined in resources, you can pass the same link style object
// when constructing the AnnotatedString using the AnnotatedString.fromHtml method.
Text(annotatedString)
Parameters
text: AnnotatedString

the text to be displayed

modifier: Modifier = Modifier

the Modifier to be applied to this layout node

color: Color = Color.Unspecified

Color to apply to the text. If Color.Unspecified, and style has no color set, this will be LocalContentColor.

fontSize: TextUnit = TextUnit.Unspecified

the size of glyphs to use when painting the text. See TextStyle.fontSize.

fontStyle: FontStyle? = null

the typeface variant to use when drawing the letters (e.g., italic). See TextStyle.fontStyle.

fontWeight: FontWeight? = null

the typeface thickness to use when painting the text (e.g., FontWeight.Bold).

fontFamily: FontFamily? = null

the font family to be used when rendering the text. See TextStyle.fontFamily.

letterSpacing: TextUnit = TextUnit.Unspecified

the amount of space to add between each letter. See TextStyle.letterSpacing.

textDecoration: TextDecoration? = null

the decorations to paint on the text (e.g., an underline). See TextStyle.textDecoration.

textAlign: TextAlign? = null

the alignment of the text within the lines of the paragraph. See TextStyle.textAlign.

lineHeight: TextUnit = TextUnit.Unspecified

line height for the Paragraph in TextUnit unit, e.g. SP or EM. See TextStyle.lineHeight.

overflow: TextOverflow = TextOverflow.Clip

how visual overflow should be handled.

softWrap: Boolean = true

whether the text should break at soft line breaks. If false, the glyphs in the text will be positioned as if there was unlimited horizontal space. If softWrap is false, overflow and TextAlign may have unexpected effects.

maxLines: Int = Int.MAX_VALUE

An optional maximum number of lines for the text to span, wrapping if necessary. If the text exceeds the given number of lines, it will be truncated according to overflow and softWrap. It is required that 1 <= minLines<= maxLines.

minLines: Int = 1

The minimum height in terms of minimum number of visible lines. It is required that 1 <= minLines<= maxLines.

inlineContent: Map<StringInlineTextContent> = mapOf()

a map storing composables that replaces certain ranges of the text, used to insert composables into text layout. See InlineTextContent.

onTextLayout: (TextLayoutResult) -> Unit = {}

callback that is executed when a new text layout is calculated. A TextLayoutResult object that callback provides contains paragraph information, size of the text, baselines and other details. The callback can be used to add additional decoration or functionality to the text. For example, to draw selection around the text.

style: TextStyle = LocalTextStyle.current

style configuration for the text such as color, font, line height etc.

TextButton

@Composable
fun TextButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shape: Shape = ButtonDefaults.textShape,
    colors: ButtonColors = ButtonDefaults.textButtonColors(),
    elevation: ButtonElevation? = null,
    border: BorderStroke? = null,
    contentPadding: PaddingValues = ButtonDefaults.TextButtonContentPadding,
    interactionSource: MutableInteractionSource? = null,
    content: @Composable RowScope.() -> Unit
): Unit

Material Design text button.

Buttons help people initiate actions, from sending an email, to sharing a document, to liking a post.

Text button image

Text buttons are typically used for less-pronounced actions, including those located in dialogs and cards. In cards, text buttons help maintain an emphasis on card content. Text buttons are used for the lowest priority actions, especially when presenting multiple options.

import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton

TextButton(onClick = { /* Do something! */ }) { Text("Text Button") }

Choose the best button for an action based on the amount of emphasis it needs. The more important an action is, the higher emphasis its button should be.

The default text style for internal Text components will be set to Typography.labelLarge.

Parameters
onClick: () -> Unit

called when this button is clicked

modifier: Modifier = Modifier

the Modifier to be applied to this button

enabled: Boolean = true

controls the enabled state of this button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

shape: Shape = ButtonDefaults.textShape

defines the shape of this button's container, border (when border is not null), and shadow (when using elevation)

colors: ButtonColors = ButtonDefaults.textButtonColors()

ButtonColors that will be used to resolve the colors for this button in different states. See ButtonDefaults.textButtonColors.

elevation: ButtonElevation? = null

ButtonElevation used to resolve the elevation for this button in different states. This controls the size of the shadow below the button. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay. A TextButton typically has no elevation, and the default value is null. See ElevatedButton for a button with elevation.

border: BorderStroke? = null

the border to draw around the container of this button

contentPadding: PaddingValues = ButtonDefaults.TextButtonContentPadding

the spacing values to apply internally between the container and the content

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this button. You can use this to change the button's appearance or preview the button in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable RowScope.() -> Unit

The content displayed on the button, expected to be text.

TextField

@Composable
fun TextField(
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    readOnly: Boolean = false,
    textStyle: TextStyle = LocalTextStyle.current,
    label: (@Composable () -> Unit)? = null,
    placeholder: (@Composable () -> Unit)? = null,
    leadingIcon: (@Composable () -> Unit)? = null,
    trailingIcon: (@Composable () -> Unit)? = null,
    prefix: (@Composable () -> Unit)? = null,
    suffix: (@Composable () -> Unit)? = null,
    supportingText: (@Composable () -> Unit)? = null,
    isError: Boolean = false,
    visualTransformation: VisualTransformation = VisualTransformation.None,
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
    keyboardActions: KeyboardActions = KeyboardActions.Default,
    singleLine: Boolean = false,
    maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
    minLines: Int = 1,
    interactionSource: MutableInteractionSource? = null,
    shape: Shape = TextFieldDefaults.shape,
    colors: TextFieldColors = TextFieldDefaults.colors()
): Unit

Material Design filled text field.

Text fields allow users to enter text into a UI. They typically appear in forms and dialogs. Filled text fields have more visual emphasis than outlined text fields, making them stand out when surrounded by other content and components.

Filled text field image

If you are looking for an outlined version, see OutlinedTextField.

If apart from input text change you also want to observe the cursor location, selection range, or IME composition use the TextField overload with the TextFieldValue parameter instead.

Parameters
value: String

the input text to be shown in the text field

onValueChange: (String) -> Unit

the callback that is triggered when the input service updates the text. An updated text comes as a parameter of the callback

modifier: Modifier = Modifier

the Modifier to be applied to this text field

enabled: Boolean = true

controls the enabled state of this text field. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

readOnly: Boolean = false

controls the editable state of the text field. When true, the text field cannot be modified. However, a user can focus it and copy text from it. Read-only text fields are usually used to display pre-filled forms that a user cannot edit.

textStyle: TextStyle = LocalTextStyle.current

the style to be applied to the input text. Defaults to LocalTextStyle.

label: (@Composable () -> Unit)? = null

the optional label to be displayed with this text field. The default text style uses Typography.bodySmall when minimized and Typography.bodyLarge when expanded.

placeholder: (@Composable () -> Unit)? = null

the optional placeholder to be displayed when the text field is in focus and the input text is empty. The default text style for internal Text is Typography.bodyLarge

leadingIcon: (@Composable () -> Unit)? = null

the optional leading icon to be displayed at the beginning of the text field container

trailingIcon: (@Composable () -> Unit)? = null

the optional trailing icon to be displayed at the end of the text field container

prefix: (@Composable () -> Unit)? = null

the optional prefix to be displayed before the input text in the text field

suffix: (@Composable () -> Unit)? = null

the optional suffix to be displayed after the input text in the text field

supportingText: (@Composable () -> Unit)? = null

the optional supporting text to be displayed below the text field

isError: Boolean = false

indicates if the text field's current value is in error. If set to true, the label, bottom indicator and trailing icon by default will be displayed in error color

visualTransformation: VisualTransformation = VisualTransformation.None

transforms the visual representation of the input value For example, you can use PasswordVisualTransformation to create a password text field. By default, no visual transformation is applied.

keyboardOptions: KeyboardOptions = KeyboardOptions.Default

software keyboard options that contains configuration such as KeyboardType and ImeAction.

keyboardActions: KeyboardActions = KeyboardActions.Default

when the input service emits an IME action, the corresponding callback is called. Note that this IME action may be different from what you specified in KeyboardOptions.imeAction.

singleLine: Boolean = false

when true, this text field becomes a single horizontally scrolling text field instead of wrapping onto multiple lines. The keyboard will be informed to not show the return key as the ImeAction. Note that maxLines parameter will be ignored as the maxLines attribute will be automatically set to 1.

maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE

the maximum height in terms of maximum number of visible lines. It is required that 1 <= minLines<= maxLines. This parameter is ignored when singleLine is true.

minLines: Int = 1

the minimum height in terms of minimum number of visible lines. It is required that 1 <= minLines<= maxLines. This parameter is ignored when singleLine is true.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this text field. You can use this to change the text field's appearance or preview the text field in different states. Note that if null is provided, interactions will still happen internally.

shape: Shape = TextFieldDefaults.shape

defines the shape of this text field's container

colors: TextFieldColors = TextFieldDefaults.colors()

TextFieldColors that will be used to resolve the colors used for this text field in different states. See TextFieldDefaults.colors.

TextField

@Composable
fun TextField(
    value: TextFieldValue,
    onValueChange: (TextFieldValue) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    readOnly: Boolean = false,
    textStyle: TextStyle = LocalTextStyle.current,
    label: (@Composable () -> Unit)? = null,
    placeholder: (@Composable () -> Unit)? = null,
    leadingIcon: (@Composable () -> Unit)? = null,
    trailingIcon: (@Composable () -> Unit)? = null,
    prefix: (@Composable () -> Unit)? = null,
    suffix: (@Composable () -> Unit)? = null,
    supportingText: (@Composable () -> Unit)? = null,
    isError: Boolean = false,
    visualTransformation: VisualTransformation = VisualTransformation.None,
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
    keyboardActions: KeyboardActions = KeyboardActions.Default,
    singleLine: Boolean = false,
    maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
    minLines: Int = 1,
    interactionSource: MutableInteractionSource? = null,
    shape: Shape = TextFieldDefaults.shape,
    colors: TextFieldColors = TextFieldDefaults.colors()
): Unit

Material Design filled text field.

Text fields allow users to enter text into a UI. They typically appear in forms and dialogs. Filled text fields have more visual emphasis than outlined text fields, making them stand out when surrounded by other content and components.

Filled text field image

If you are looking for an outlined version, see OutlinedTextField.

This overload provides access to the input text, cursor position, selection range and IME composition. If you only want to observe an input text change, use the TextField overload with the String parameter instead.

Parameters
value: TextFieldValue

the input TextFieldValue to be shown in the text field

onValueChange: (TextFieldValue) -> Unit

the callback that is triggered when the input service updates values in TextFieldValue. An updated TextFieldValue comes as a parameter of the callback

modifier: Modifier = Modifier

the Modifier to be applied to this text field

enabled: Boolean = true

controls the enabled state of this text field. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

readOnly: Boolean = false

controls the editable state of the text field. When true, the text field cannot be modified. However, a user can focus it and copy text from it. Read-only text fields are usually used to display pre-filled forms that a user cannot edit.

textStyle: TextStyle = LocalTextStyle.current

the style to be applied to the input text. Defaults to LocalTextStyle.

label: (@Composable () -> Unit)? = null

the optional label to be displayed with this text field. The default text style uses Typography.bodySmall when minimized and Typography.bodyLarge when expanded.

placeholder: (@Composable () -> Unit)? = null

the optional placeholder to be displayed when the text field is in focus and the input text is empty. The default text style for internal Text is Typography.bodyLarge

leadingIcon: (@Composable () -> Unit)? = null

the optional leading icon to be displayed at the beginning of the text field container

trailingIcon: (@Composable () -> Unit)? = null

the optional trailing icon to be displayed at the end of the text field container

prefix: (@Composable () -> Unit)? = null

the optional prefix to be displayed before the input text in the text field

suffix: (@Composable () -> Unit)? = null

the optional suffix to be displayed after the input text in the text field

supportingText: (@Composable () -> Unit)? = null

the optional supporting text to be displayed below the text field

isError: Boolean = false

indicates if the text field's current value is in error state. If set to true, the label, bottom indicator and trailing icon by default will be displayed in error color

visualTransformation: VisualTransformation = VisualTransformation.None

transforms the visual representation of the input value. For example, you can use PasswordVisualTransformation to create a password text field. By default, no visual transformation is applied.

keyboardOptions: KeyboardOptions = KeyboardOptions.Default

software keyboard options that contains configuration such as KeyboardType and ImeAction.

keyboardActions: KeyboardActions = KeyboardActions.Default

when the input service emits an IME action, the corresponding callback is called. Note that this IME action may be different from what you specified in KeyboardOptions.imeAction.

singleLine: Boolean = false

when true, this text field becomes a single horizontally scrolling text field instead of wrapping onto multiple lines. The keyboard will be informed to not show the return key as the ImeAction. Note that maxLines parameter will be ignored as the maxLines attribute will be automatically set to 1.

maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE

the maximum height in terms of maximum number of visible lines. It is required that 1 <= minLines<= maxLines. This parameter is ignored when singleLine is true.

minLines: Int = 1

the minimum height in terms of minimum number of visible lines. It is required that 1 <= minLines<= maxLines. This parameter is ignored when singleLine is true.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this text field. You can use this to change the text field's appearance or preview the text field in different states. Note that if null is provided, interactions will still happen internally.

shape: Shape = TextFieldDefaults.shape

defines the shape of this text field's container

colors: TextFieldColors = TextFieldDefaults.colors()

TextFieldColors that will be used to resolve the colors used for this text field in different states. See TextFieldDefaults.colors.

@Composable
fun TextField(
    state: TextFieldState,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    readOnly: Boolean = false,
    textStyle: TextStyle = LocalTextStyle.current,
    labelPosition: TextFieldLabelPosition = TextFieldLabelPosition.Attached(),
    label: (@Composable TextFieldLabelScope.() -> Unit)? = null,
    placeholder: (@Composable () -> Unit)? = null,
    leadingIcon: (@Composable () -> Unit)? = null,
    trailingIcon: (@Composable () -> Unit)? = null,
    prefix: (@Composable () -> Unit)? = null,
    suffix: (@Composable () -> Unit)? = null,
    supportingText: (@Composable () -> Unit)? = null,
    isError: Boolean = false,
    inputTransformation: InputTransformation? = null,
    outputTransformation: OutputTransformation? = null,
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
    onKeyboardAction: KeyboardActionHandler? = null,
    lineLimits: TextFieldLineLimits = TextFieldLineLimits.Default,
    onTextLayout: (Density.(getResult: () -> TextLayoutResult?) -> Unit)? = null,
    scrollState: ScrollState = rememberScrollState(),
    shape: Shape = TextFieldDefaults.shape,
    colors: TextFieldColors = TextFieldDefaults.colors(),
    contentPadding: PaddingValues = if (label == null || labelPosition is TextFieldLabelPosition.Above) { TextFieldDefaults.contentPaddingWithoutLabel() } else { TextFieldDefaults.contentPaddingWithLabel() },
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design filled text field.

Text fields allow users to enter text into a UI. They typically appear in forms and dialogs. Filled text fields have more visual emphasis than outlined text fields, making them stand out when surrounded by other content and components.

Filled text field image

If you are looking for an outlined version, see OutlinedTextField. For a text field specifically designed for passwords or other secure content, see SecureTextField.

This overload of TextField uses TextFieldState to keep track of its text content and position of the cursor or selection.

A simple single line text field looks like:

import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.remember

TextField(
    state = rememberTextFieldState(),
    lineLimits = TextFieldLineLimits.SingleLine,
    label = { Text("Label") },
)

You can control the initial text input and selection:

import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.remember
import androidx.compose.ui.text.TextRange

val state = rememberTextFieldState("Initial text", TextRange(0, 12))
TextField(
    state = state,
    lineLimits = TextFieldLineLimits.SingleLine,
    label = { Text("Label") },
)

Use input and output transformations to control user input and the displayed text:

import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.input.InputTransformation
import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.insert
import androidx.compose.foundation.text.input.maxLength
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.foundation.text.input.then
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.remember
import androidx.compose.ui.text.input.KeyboardType
import androidx.core.text.isDigitsOnly

TextField(
    state = rememberTextFieldState(),
    lineLimits = TextFieldLineLimits.SingleLine,
    label = { Text("Phone number") },
    keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
    // Input transformation to limit user input to 10 digits
    inputTransformation =
        InputTransformation.maxLength(10).then {
            if (!this.asCharSequence().isDigitsOnly()) {
                revertAllChanges()
            }
        },
    outputTransformation = {
        // Output transformation to format as a phone number: (XXX) XXX-XXXX
        if (length > 0) insert(0, "(")
        if (length > 4) insert(4, ") ")
        if (length > 9) insert(9, "-")
    },
)

You may provide a placeholder:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material3.Checkbox
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldLabelPosition
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

var alwaysMinimizeLabel by remember { mutableStateOf(false) }
Column {
    Row {
        Checkbox(checked = alwaysMinimizeLabel, onCheckedChange = { alwaysMinimizeLabel = it })
        Text("Show placeholder even when unfocused")
    }
    Spacer(Modifier.height(16.dp))
    TextField(
        state = rememberTextFieldState(),
        lineLimits = TextFieldLineLimits.SingleLine,
        label = { Text("Email") },
        labelPosition = TextFieldLabelPosition.Attached(alwaysMinimize = alwaysMinimizeLabel),
        placeholder = { Text("example@gmail.com") }
    )
}

You can also provide leading and trailing icons:

import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.clearText
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.remember

val state = rememberTextFieldState()

TextField(
    state = state,
    lineLimits = TextFieldLineLimits.SingleLine,
    label = { Text("Label") },
    leadingIcon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
    trailingIcon = {
        IconButton(onClick = { state.clearText() }) {
            Icon(Icons.Filled.Clear, contentDescription = "Clear text")
        }
    }
)

You can also provide a prefix or suffix to the text:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material3.Checkbox
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldLabelPosition
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

var alwaysMinimizeLabel by remember { mutableStateOf(false) }
Column {
    Row {
        Checkbox(checked = alwaysMinimizeLabel, onCheckedChange = { alwaysMinimizeLabel = it })
        Text("Show placeholder even when unfocused")
    }
    Spacer(Modifier.height(16.dp))
    TextField(
        state = rememberTextFieldState(),
        lineLimits = TextFieldLineLimits.SingleLine,
        label = { Text("Label") },
        labelPosition = TextFieldLabelPosition.Attached(alwaysMinimize = alwaysMinimizeLabel),
        prefix = { Text("www.") },
        suffix = { Text(".com") },
        placeholder = { Text("google") },
    )
}

To handle the error input state, use isError parameter:

import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.error
import androidx.compose.ui.semantics.maxTextLength
import androidx.compose.ui.semantics.semantics

val errorMessage = "Text input too long"
val state = rememberTextFieldState()
var isError by rememberSaveable { mutableStateOf(false) }
val charLimit = 10

fun validate(text: CharSequence) {
    isError = text.length > charLimit
}

LaunchedEffect(Unit) {
    // Run validation whenever text value changes
    snapshotFlow { state.text }.collect { validate(it) }
}
TextField(
    state = state,
    lineLimits = TextFieldLineLimits.SingleLine,
    label = { Text(if (isError) "Username*" else "Username") },
    supportingText = {
        Row {
            Text(if (isError) errorMessage else "", Modifier.clearAndSetSemantics {})
            Spacer(Modifier.weight(1f))
            Text("Limit: ${state.text.length}/$charLimit")
        }
    },
    isError = isError,
    onKeyboardAction = { validate(state.text) },
    modifier =
        Modifier.semantics {
            maxTextLength = charLimit
            // Provide localized description of the error
            if (isError) error(errorMessage)
        }
)

Additionally, you may provide additional message at the bottom:

import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.remember

TextField(
    state = rememberTextFieldState(),
    lineLimits = TextFieldLineLimits.SingleLine,
    label = { Text("Label") },
    supportingText = {
        Text("Supporting text that is long and perhaps goes onto another line.")
    },
)

You can change the content padding to create a dense text field:

import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

TextField(
    state = rememberTextFieldState(),
    lineLimits = TextFieldLineLimits.SingleLine,
    label = { Text("Label") },
    // Need to set a min height using `heightIn` to override the default
    modifier = Modifier.heightIn(min = 48.dp),
    contentPadding = PaddingValues(top = 4.dp, bottom = 4.dp, start = 12.dp, end = 12.dp),
)

Hiding a software keyboard on IME action performed:

import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.text.input.ImeAction

val keyboardController = LocalSoftwareKeyboardController.current
TextField(
    state = rememberTextFieldState(),
    label = { Text("Label") },
    keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
    onKeyboardAction = { keyboardController?.hide() }
)
Parameters
state: TextFieldState

TextFieldState object that holds the internal editing state of the text field.

modifier: Modifier = Modifier

the Modifier to be applied to this text field.

enabled: Boolean = true

controls the enabled state of this text field. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

readOnly: Boolean = false

controls the editable state of the text field. When true, the text field cannot be modified. However, a user can focus it and copy text from it. Read-only text fields are usually used to display pre-filled forms that a user cannot edit.

textStyle: TextStyle = LocalTextStyle.current

the style to be applied to the input text. Defaults to LocalTextStyle.

labelPosition: TextFieldLabelPosition = TextFieldLabelPosition.Attached()

the position of the label. See TextFieldLabelPosition.

label: (@Composable TextFieldLabelScope.() -> Unit)? = null

the optional label to be displayed with this text field. The default text style uses Typography.bodySmall when minimized and Typography.bodyLarge when expanded.

placeholder: (@Composable () -> Unit)? = null

the optional placeholder to be displayed when the input text is empty. The default text style uses Typography.bodyLarge.

leadingIcon: (@Composable () -> Unit)? = null

the optional leading icon to be displayed at the beginning of the text field container.

trailingIcon: (@Composable () -> Unit)? = null

the optional trailing icon to be displayed at the end of the text field container.

prefix: (@Composable () -> Unit)? = null

the optional prefix to be displayed before the input text in the text field.

suffix: (@Composable () -> Unit)? = null

the optional suffix to be displayed after the input text in the text field.

supportingText: (@Composable () -> Unit)? = null

the optional supporting text to be displayed below the text field.

isError: Boolean = false

indicates if the text field's current value is in error. When true, the components of the text field will be displayed in an error color, and an error will be announced to accessibility services.

inputTransformation: InputTransformation? = null

optional InputTransformation that will be used to transform changes to the TextFieldState made by the user. The transformation will be applied to changes made by hardware and software keyboard events, pasting or dropping text, accessibility services, and tests. The transformation will not be applied when changing the state programmatically, or when the transformation is changed. If the transformation is changed on an existing text field, it will be applied to the next user edit. The transformation will not immediately affect the current state.

outputTransformation: OutputTransformation? = null

optional OutputTransformation that transforms how the contents of the text field are presented.

keyboardOptions: KeyboardOptions = KeyboardOptions.Default

software keyboard options that contains configuration such as KeyboardType and ImeAction.

onKeyboardAction: KeyboardActionHandler? = null

called when the user presses the action button in the input method editor (IME), or by pressing the enter key on a hardware keyboard. By default this parameter is null, and would execute the default behavior for a received IME Action e.g., ImeAction.Done would close the keyboard, ImeAction.Next would switch the focus to the next focusable item on the screen.

lineLimits: TextFieldLineLimits = TextFieldLineLimits.Default

whether the text field should be SingleLine, scroll horizontally, and ignore newlines; or MultiLine and grow and scroll vertically. If SingleLine is passed, all newline characters ('\n') within the text will be replaced with regular whitespace (' ').

onTextLayout: (Density.(getResult: () -> TextLayoutResult?) -> Unit)? = null

Callback that is executed when the text layout becomes queryable. The callback receives a function that returns a TextLayoutResult if the layout can be calculated, or null if it cannot. The function reads the layout result from a snapshot state object, and will invalidate its caller when the layout result changes. A TextLayoutResult object contains paragraph information, size of the text, baselines and other details. Density scope is the one that was used while creating the given text layout.

scrollState: ScrollState = rememberScrollState()

scroll state that manages either horizontal or vertical scroll of the text field. If lineLimits is SingleLine, this text field is treated as single line with horizontal scroll behavior. Otherwise, the text field becomes vertically scrollable.

shape: Shape = TextFieldDefaults.shape

defines the shape of this text field's container.

colors: TextFieldColors = TextFieldDefaults.colors()

TextFieldColors that will be used to resolve the colors used for this text field in different states. See TextFieldDefaults.colors.

contentPadding: PaddingValues = if (label == null || labelPosition is TextFieldLabelPosition.Above) { TextFieldDefaults.contentPaddingWithoutLabel() } else { TextFieldDefaults.contentPaddingWithLabel() }

the padding applied to the inner text field that separates it from the surrounding elements of the text field. Note that the padding values may not be respected if they are incompatible with the text field's size constraints or layout. See TextFieldDefaults.contentPaddingWithLabel and TextFieldDefaults.contentPaddingWithoutLabel.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this text field. You can use this to change the text field's appearance or preview the text field in different states. Note that if null is provided, interactions will still happen internally.

TimeInput

@Composable
@ExperimentalMaterial3Api
fun TimeInput(
    state: TimePickerState,
    modifier: Modifier = Modifier,
    colors: TimePickerColors = TimePickerDefaults.colors()
): Unit

Time pickers help users select and set a specific time.

Shows a time input that allows the user to enter the time via two text fields, one for minutes and one for hours Subscribe to updates through TimePickerState

import androidx.compose.foundation.layout.Box
import androidx.compose.material3.Button
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.TimeInput
import androidx.compose.material3.TimePicker
import androidx.compose.material3.rememberTimePickerState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.window.Dialog

var showTimePicker by remember { mutableStateOf(false) }
val state = rememberTimePickerState()
val formatter = remember { SimpleDateFormat("hh:mm a", Locale.getDefault()) }
val snackState = remember { SnackbarHostState() }
val snackScope = rememberCoroutineScope()

Box(propagateMinConstraints = false) {
    Button(modifier = Modifier.align(Alignment.Center), onClick = { showTimePicker = true }) {
        Text("Set Time")
    }
    SnackbarHost(hostState = snackState)
}

if (showTimePicker) {
    TimePickerDialog(
        onCancel = { showTimePicker = false },
        onConfirm = {
            val cal = Calendar.getInstance()
            cal.set(Calendar.HOUR_OF_DAY, state.hour)
            cal.set(Calendar.MINUTE, state.minute)
            cal.isLenient = false
            snackScope.launch {
                snackState.showSnackbar("Entered time: ${formatter.format(cal.time)}")
            }
            showTimePicker = false
        },
    ) {
        TimeInput(state = state)
    }
}
Parameters
state: TimePickerState

state for this timepicker, allows to subscribe to changes to TimePickerState.hour and TimePickerState.minute, and set the initial time for this picker.

modifier: Modifier = Modifier

the Modifier to be applied to this time input

colors: TimePickerColors = TimePickerDefaults.colors()

colors TimePickerColors that will be used to resolve the colors used for this time input in different states. See TimePickerDefaults.colors.

@Composable
@ExperimentalMaterial3Api
fun TimePicker(
    state: TimePickerState,
    modifier: Modifier = Modifier,
    colors: TimePickerColors = TimePickerDefaults.colors(),
    layoutType: TimePickerLayoutType = TimePickerDefaults.layoutType()
): Unit

Material Design time picker.

Time pickers help users select and set a specific time.

Shows a picker that allows the user to select time. Subscribe to updates through TimePickerState

Time picker image

import androidx.compose.foundation.layout.Box
import androidx.compose.material3.Button
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.TimePicker
import androidx.compose.material3.rememberTimePickerState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.window.Dialog

var showTimePicker by remember { mutableStateOf(false) }
val state = rememberTimePickerState()
val formatter = remember { SimpleDateFormat("hh:mm a", Locale.getDefault()) }
val snackState = remember { SnackbarHostState() }
val snackScope = rememberCoroutineScope()

Box(propagateMinConstraints = false) {
    Button(modifier = Modifier.align(Alignment.Center), onClick = { showTimePicker = true }) {
        Text("Set Time")
    }
    SnackbarHost(hostState = snackState)
}

if (showTimePicker) {
    TimePickerDialog(
        onCancel = { showTimePicker = false },
        onConfirm = {
            val cal = Calendar.getInstance()
            cal.set(Calendar.HOUR_OF_DAY, state.hour)
            cal.set(Calendar.MINUTE, state.minute)
            cal.isLenient = false
            snackScope.launch {
                snackState.showSnackbar("Entered time: ${formatter.format(cal.time)}")
            }
            showTimePicker = false
        },
    ) {
        TimePicker(state = state)
    }
}
import androidx.compose.foundation.layout.Box
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Keyboard
import androidx.compose.material.icons.outlined.Schedule
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.TimeInput
import androidx.compose.material3.TimePicker
import androidx.compose.material3.rememberTimePickerState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.window.Dialog

var showTimePicker by remember { mutableStateOf(false) }
val state = rememberTimePickerState()
val formatter = remember { SimpleDateFormat("hh:mm a", Locale.getDefault()) }
val snackState = remember { SnackbarHostState() }
val showingPicker = remember { mutableStateOf(true) }
val snackScope = rememberCoroutineScope()
val configuration = LocalConfiguration.current

Box(propagateMinConstraints = false) {
    Button(modifier = Modifier.align(Alignment.Center), onClick = { showTimePicker = true }) {
        Text("Set Time")
    }
    SnackbarHost(hostState = snackState)
}

if (showTimePicker) {
    TimePickerDialog(
        title =
            if (showingPicker.value) {
                "Select Time "
            } else {
                "Enter Time"
            },
        onCancel = { showTimePicker = false },
        onConfirm = {
            val cal = Calendar.getInstance()
            cal.set(Calendar.HOUR_OF_DAY, state.hour)
            cal.set(Calendar.MINUTE, state.minute)
            cal.isLenient = false
            snackScope.launch {
                snackState.showSnackbar("Entered time: ${formatter.format(cal.time)}")
            }
            showTimePicker = false
        },
        toggle = {
            if (configuration.screenHeightDp > 400) {
                IconButton(onClick = { showingPicker.value = !showingPicker.value }) {
                    val icon =
                        if (showingPicker.value) {
                            Icons.Outlined.Keyboard
                        } else {
                            Icons.Outlined.Schedule
                        }
                    Icon(
                        icon,
                        contentDescription =
                            if (showingPicker.value) {
                                "Switch to Text Input"
                            } else {
                                "Switch to Touch Input"
                            }
                    )
                }
            }
        }
    ) {
        if (showingPicker.value && configuration.screenHeightDp > 400) {
            TimePicker(state = state)
        } else {
            TimeInput(state = state)
        }
    }
}

state state for this timepicker, allows to subscribe to changes to TimePickerState.hour and TimePickerState.minute, and set the initial time for this picker.

Parameters
state: TimePickerState

state for this time input, allows to subscribe to changes to TimePickerState.hour and TimePickerState.minute, and set the initial time for this input.

modifier: Modifier = Modifier

the Modifier to be applied to this time input

colors: TimePickerColors = TimePickerDefaults.colors()

colors TimePickerColors that will be used to resolve the colors used for this time picker in different states. See TimePickerDefaults.colors.

layoutType: TimePickerLayoutType = TimePickerDefaults.layoutType()

, the different TimePickerLayoutType supported by this time picker, it will change the position and sizing of different components of the timepicker.

TimePickerState

@ExperimentalMaterial3Api
fun TimePickerState(initialHour: Int, initialMinute: Int, is24Hour: Boolean): TimePickerState

Factory function for the default implementation of TimePickerState should be used in most cases.

Parameters
initialHour: Int

starting hour for this state, will be displayed in the time picker when launched Ranges from 0 to 23

initialMinute: Int

starting minute for this state, will be displayed in the time picker when launched. Ranges from 0 to 59

is24Hour: Boolean

The format for this time picker. false for 12 hour format with an AM/PM toggle or true for 24 hour format without toggle. Defaults to follow system setting.

ToggleButton

@Composable
@ExperimentalMaterial3ExpressiveApi
fun ToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shapes: ButtonShapes = ToggleButtonDefaults.shapes(),
    colors: ToggleButtonColors = ToggleButtonDefaults.toggleButtonColors(),
    elevation: ButtonElevation? = ButtonDefaults.buttonElevation(),
    border: BorderStroke? = null,
    contentPadding: PaddingValues = ToggleButtonDefaults.ContentPadding,
    interactionSource: MutableInteractionSource? = null,
    content: @Composable RowScope.() -> Unit
): Unit

TODO link to mio page when available.

Toggle button is a toggleable button that switches between primary and tonal colors depending on checked's value. It also morphs between the three shapes provided in shapes depending on the state of the interaction with the toggle button as long as the three shapes provided our CornerBasedShapes. If a shape in shapes isn't a CornerBasedShape, then toggle button will toggle between the ButtonShapes according to user interaction.

TODO link to an image when available

see Button for a static button that doesn't need to be toggled. see IconToggleButton for a toggleable button where the content is specifically an Icon.

import androidx.compose.material3.Text
import androidx.compose.material3.ToggleButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var checked by remember { mutableStateOf(false) }
ToggleButton(checked = checked, onCheckedChange = { checked = it }) { Text("Button") }
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.outlined.Favorite
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ElevatedToggleButton
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.material3.ToggleButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier

var checked by remember { mutableStateOf(false) }
ElevatedToggleButton(checked = checked, onCheckedChange = { checked = it }) {
    Icon(
        if (checked) Icons.Filled.Favorite else Icons.Outlined.Favorite,
        contentDescription = "Localized description",
        modifier = Modifier.size(ButtonDefaults.IconSize)
    )
    Spacer(Modifier.size(ButtonDefaults.IconSpacing))
    Text("Like")
}

For a ToggleButton that uses a round unchecked shape and morphs into a square checked shape:

ToggleButton uses the small button design as default. For a ToggleButton that uses the design for extra small, medium, large, or extra large buttons:

import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.material3.ToggleButton
import androidx.compose.material3.ToggleButtonDefaults
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier

var checked by remember { mutableStateOf(false) }
ToggleButton(
    checked = checked,
    onCheckedChange = { checked = it },
    modifier = Modifier.heightIn(ButtonDefaults.XSmallContainerHeight),
    shapes =
        ToggleButtonDefaults.shapes(
            shape = ToggleButtonDefaults.XSmallSquareShape,
            pressedShape = ToggleButtonDefaults.XSmallPressedShape,
            checkedShape = ToggleButtonDefaults.checkedShape
        ),
    contentPadding = ButtonDefaults.XSmallContentPadding
) {
    Icon(
        if (checked) Icons.Filled.Edit else Icons.Outlined.Edit,
        contentDescription = "Localized description",
        modifier = Modifier.size(ButtonDefaults.XSmallIconSize)
    )
    Spacer(Modifier.size(ButtonDefaults.XSmallIconSpacing))
    Text("Label")
}
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.ToggleButton
import androidx.compose.material3.ToggleButtonDefaults
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier

var checked by remember { mutableStateOf(false) }
ToggleButton(
    checked = checked,
    onCheckedChange = { checked = it },
    modifier = Modifier.heightIn(ButtonDefaults.MediumContainerHeight),
    shapes =
        ToggleButtonDefaults.shapes(
            shape = ToggleButtonDefaults.MediumSquareShape,
            pressedShape = ToggleButtonDefaults.MediumPressedShape,
            checkedShape = ToggleButtonDefaults.checkedShape
        ),
    contentPadding = ButtonDefaults.MediumContentPadding
) {
    Icon(
        if (checked) Icons.Filled.Edit else Icons.Outlined.Edit,
        contentDescription = "Localized description",
        modifier = Modifier.size(ButtonDefaults.MediumIconSize)
    )
    Spacer(Modifier.size(ButtonDefaults.MediumIconSpacing))
    Text(text = "Label", style = MaterialTheme.typography.titleMedium)
}
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.ToggleButton
import androidx.compose.material3.ToggleButtonDefaults
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier

var checked by remember { mutableStateOf(false) }
ToggleButton(
    checked = checked,
    onCheckedChange = { checked = it },
    modifier = Modifier.heightIn(ButtonDefaults.LargeContainerHeight),
    shapes =
        ToggleButtonDefaults.shapes(
            shape = ToggleButtonDefaults.LargeSquareShape,
            pressedShape = ToggleButtonDefaults.LargePressedShape,
            checkedShape = ToggleButtonDefaults.checkedShape
        ),
    contentPadding = ButtonDefaults.LargeContentPadding
) {
    Icon(
        if (checked) Icons.Filled.Edit else Icons.Outlined.Edit,
        contentDescription = "Localized description",
        modifier = Modifier.size(ButtonDefaults.LargeIconSize)
    )
    Spacer(Modifier.size(ButtonDefaults.LargeIconSpacing))
    Text(text = "Label", style = MaterialTheme.typography.headlineSmall)
}
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.ToggleButton
import androidx.compose.material3.ToggleButtonDefaults
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier

var checked by remember { mutableStateOf(false) }
ToggleButton(
    checked = checked,
    onCheckedChange = { checked = it },
    modifier = Modifier.heightIn(ButtonDefaults.XLargeContainerHeight),
    shapes =
        ToggleButtonDefaults.shapes(
            shape = ToggleButtonDefaults.XLargeSquareShape,
            pressedShape = ToggleButtonDefaults.XLargePressedShape,
            checkedShape = ToggleButtonDefaults.checkedShape
        ),
    contentPadding = ButtonDefaults.XLargeContentPadding
) {
    Icon(
        if (checked) Icons.Filled.Edit else Icons.Outlined.Edit,
        contentDescription = "Localized description",
        modifier = Modifier.size(ButtonDefaults.XLargeIconSize)
    )
    Spacer(Modifier.size(ButtonDefaults.XLargeIconSpacing))
    Text(text = "Label", style = MaterialTheme.typography.headlineLarge)
}
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ButtonShapes
import androidx.compose.material3.Text
import androidx.compose.material3.ToggleButton
import androidx.compose.material3.ToggleButtonDefaults
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var checked by remember { mutableStateOf(false) }
val shapes =
    ButtonShapes(
        shape = ToggleButtonDefaults.roundShape,
        pressedShape = ToggleButtonDefaults.pressedShape,
        checkedShape = ToggleButtonDefaults.squareShape
    )
ToggleButton(checked = checked, onCheckedChange = { checked = it }, shapes = shapes) {
    Text("Button")
}
Parameters
checked: Boolean

whether the toggle button is toggled on or off.

onCheckedChange: (Boolean) -> Unit

called when the toggle button is clicked.

modifier: Modifier = Modifier

the Modifier to be applied to the toggle button.

enabled: Boolean = true

controls the enabled state of this toggle button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

shapes: ButtonShapes = ToggleButtonDefaults.shapes()

the ButtonShapes that the toggle button will morph between depending on the user's interaction with the toggle button.

colors: ToggleButtonColors = ToggleButtonDefaults.toggleButtonColors()

ToggleButtonColors that will be used to resolve the colors used for this toggle button in different states. See ToggleButtonDefaults.toggleButtonColors.

elevation: ButtonElevation? = ButtonDefaults.buttonElevation()

ButtonElevation used to resolve the elevation for this button in different states. This controls the size of the shadow below the button. See ButtonElevation.shadowElevation. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay.

border: BorderStroke? = null

the border to draw around the container of this toggle button.

contentPadding: PaddingValues = ToggleButtonDefaults.ContentPadding

the spacing values to apply internally between the container and the content

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this toggle button. You can use this to change the toggle button's appearance or preview the toggle button in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable RowScope.() -> Unit

The content displayed on the toggle button, expected to be text, icon or image.

ToggleFloatingActionButton

@ExperimentalMaterial3ExpressiveApi
@Composable
fun ToggleFloatingActionButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    containerColor: (Float) -> Color = ToggleFloatingActionButtonDefaults.containerColor(),
    contentAlignment: Alignment = Alignment.TopEnd,
    containerSize: (Float) -> Dp = ToggleFloatingActionButtonDefaults.containerSize(),
    containerCornerRadius: (Float) -> Dp = ToggleFloatingActionButtonDefaults.containerCornerRadius(),
    content: @Composable ToggleFloatingActionButtonScope.() -> Unit
): Unit

Toggleable FAB supports animating its container size, corner radius, and color when it is toggled, and should be used in conjunction with a FloatingActionButtonMenu to provide additional choices to the user after clicking the FAB.

Use ToggleFloatingActionButtonDefaults.animateIcon to animate the color and size of the icon while the ToggleFloatingActionButton is being toggled.

import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Label
import androidx.compose.material.icons.automirrored.filled.Message
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Archive
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Contacts
import androidx.compose.material.icons.filled.People
import androidx.compose.material.icons.filled.Snooze
import androidx.compose.material3.FloatingActionButtonMenu
import androidx.compose.material3.FloatingActionButtonMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.material3.ToggleFloatingActionButton
import androidx.compose.material3.ToggleFloatingActionButtonDefaults.animateIcon
import androidx.compose.material3.animateFloatingActionButton
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.semantics.CustomAccessibilityAction
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.customActions
import androidx.compose.ui.semantics.isTraversalGroup
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.stateDescription
import androidx.compose.ui.semantics.traversalIndex
import androidx.compose.ui.unit.dp

val listState = rememberLazyListState()
val fabVisible by remember { derivedStateOf { listState.firstVisibleItemIndex == 0 } }

Box {
    LazyColumn(state = listState, modifier = Modifier.fillMaxSize()) {
        for (index in 0 until 100) {
            item { Text(text = "List item - $index", modifier = Modifier.padding(24.dp)) }
        }
    }

    val items =
        listOf(
            Icons.AutoMirrored.Filled.Message to "Reply",
            Icons.Filled.People to "Reply all",
            Icons.Filled.Contacts to "Forward",
            Icons.Filled.Snooze to "Snooze",
            Icons.Filled.Archive to "Archive",
            Icons.AutoMirrored.Filled.Label to "Label",
        )

    var fabMenuExpanded by rememberSaveable { mutableStateOf(false) }

    BackHandler(fabMenuExpanded) { fabMenuExpanded = false }

    FloatingActionButtonMenu(
        modifier = Modifier.align(Alignment.BottomEnd),
        expanded = fabMenuExpanded,
        button = {
            ToggleFloatingActionButton(
                modifier =
                    Modifier.semantics {
                            traversalIndex = -1f
                            stateDescription = if (fabMenuExpanded) "Expanded" else "Collapsed"
                            contentDescription = "Toggle menu"
                        }
                        .animateFloatingActionButton(
                            visible = fabVisible || fabMenuExpanded,
                            alignment = Alignment.BottomEnd
                        ),
                checked = fabMenuExpanded,
                onCheckedChange = { fabMenuExpanded = !fabMenuExpanded }
            ) {
                val imageVector by remember {
                    derivedStateOf {
                        if (checkedProgress > 0.5f) Icons.Filled.Close else Icons.Filled.Add
                    }
                }
                Icon(
                    painter = rememberVectorPainter(imageVector),
                    contentDescription = null,
                    modifier = Modifier.animateIcon({ checkedProgress })
                )
            }
        }
    ) {
        items.forEachIndexed { i, item ->
            FloatingActionButtonMenuItem(
                modifier =
                    Modifier.semantics {
                        isTraversalGroup = true
                        // Add a custom a11y action to allow closing the menu when focusing
                        // the last menu item, since the close button comes before the first
                        // menu item in the traversal order.
                        if (i == items.size - 1) {
                            customActions =
                                listOf(
                                    CustomAccessibilityAction(
                                        label = "Close menu",
                                        action = {
                                            fabMenuExpanded = false
                                            true
                                        }
                                    )
                                )
                        }
                    },
                onClick = { fabMenuExpanded = false },
                icon = { Icon(item.first, contentDescription = null) },
                text = { Text(text = item.second) },
            )
        }
    }
}
Parameters
checked: Boolean

whether this Toggleable FAB is checked

onCheckedChange: (Boolean) -> Unit

callback to be invoked when this Toggleable FAB is clicked, therefore the change of the state in requested

modifier: Modifier = Modifier

the Modifier to be applied to this Toggleable FAB

containerColor: (Float) -> Color = ToggleFloatingActionButtonDefaults.containerColor()

the color used for the background of this Toggleable FAB, based on the checked progress value from 0-1

contentAlignment: Alignment = Alignment.TopEnd

the alignment of this Toggleable FAB when checked

containerSize: (Float) -> Dp = ToggleFloatingActionButtonDefaults.containerSize()

the size of this Toggleable FAB, based on the checked progress value from 0-1

containerCornerRadius: (Float) -> Dp = ToggleFloatingActionButtonDefaults.containerCornerRadius()

the corner radius of this Toggleable FAB, based on the checked progress value from 0-1

content: @Composable ToggleFloatingActionButtonScope.() -> Unit

the content of this Toggleable FAB, typically an Icon that switches from an Add to a Close sign at 50% checked progress

TonalToggleButton

@Composable
@ExperimentalMaterial3ExpressiveApi
fun TonalToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shapes: ButtonShapes = ToggleButtonDefaults.shapes(),
    colors: ToggleButtonColors = ToggleButtonDefaults.tonalToggleButtonColors(),
    elevation: ButtonElevation? = ButtonDefaults.filledTonalButtonElevation(),
    border: BorderStroke? = null,
    contentPadding: PaddingValues = ToggleButtonDefaults.ContentPadding,
    interactionSource: MutableInteractionSource? = null,
    content: @Composable RowScope.() -> Unit
): Unit

TODO link to mio page when available.

Toggle button is a toggleable button that switches between primary and tonal colors depending on checked's value. It also morphs between the three shapes provided in shapes depending on the state of the interaction with the toggle button as long as the three shapes provided our CornerBasedShapes. If a shape in shapes isn't a CornerBasedShape, then toggle button will toggle between the ButtonShapes according to user interaction.

TODO link to an image when available

tonal toggle buttons are medium-emphasis buttons that is an alternative middle ground between default ToggleButtons (filled) and OutlinedToggleButtons. They can be used in contexts where lower-priority button requires slightly more emphasis than an outline would give. Tonal toggle buttons use the secondary color mapping.

see FilledTonalButton for a static button that doesn't need to be toggled. see FilledTonalIconToggleButton for a toggleable button where the content is specifically an Icon.

import androidx.compose.material3.Text
import androidx.compose.material3.ToggleButton
import androidx.compose.material3.TonalToggleButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var checked by remember { mutableStateOf(false) }
TonalToggleButton(checked = checked, onCheckedChange = { checked = it }) {
    Text("Tonal Button")
}
Parameters
checked: Boolean

whether the toggle button is toggled on or off.

onCheckedChange: (Boolean) -> Unit

called when the toggle button is clicked.

modifier: Modifier = Modifier

the Modifier to be applied to the toggle button.

enabled: Boolean = true

controls the enabled state of this toggle button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

shapes: ButtonShapes = ToggleButtonDefaults.shapes()

the ButtonShapes that the toggle button will morph between depending on the user's interaction with the toggle button.

colors: ToggleButtonColors = ToggleButtonDefaults.tonalToggleButtonColors()

ToggleButtonColors that will be used to resolve the colors used for this toggle button in different states. See ToggleButtonDefaults.tonalToggleButtonColors.

elevation: ButtonElevation? = ButtonDefaults.filledTonalButtonElevation()

ButtonElevation used to resolve the elevation for this button in different states. This controls the size of the shadow below the button. Additionally, when the container color is ColorScheme.surface, this controls the amount of primary color applied as an overlay.

border: BorderStroke? = null

the border to draw around the container of this toggle button.

contentPadding: PaddingValues = ToggleButtonDefaults.ContentPadding

the spacing values to apply internally between the container and the content

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this toggle button. You can use this to change the toggle button's appearance or preview the toggle button in different states. Note that if null is provided, interactions will still happen internally.

content: @Composable RowScope.() -> Unit

The content displayed on the toggle button, expected to be text, icon or image.

@Composable
@ExperimentalMaterial3Api
fun TooltipBox(
    positionProvider: PopupPositionProvider,
    tooltip: @Composable TooltipScope.() -> Unit,
    state: TooltipState,
    modifier: Modifier = Modifier,
    onDismissRequest: (() -> Unit)? = null,
    focusable: Boolean = true,
    enableUserInput: Boolean = true,
    content: @Composable () -> Unit
): Unit

Material TooltipBox that wraps a composable with a tooltip.

tooltips provide a descriptive message for an anchor. It can be used to call the users attention to the anchor.

Tooltip that is invoked when the anchor is long pressed:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState

TooltipBox(
    positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
    tooltip = { PlainTooltip { Text("Add to favorites") } },
    state = rememberTooltipState()
) {
    IconButton(onClick = { /* Icon button's click event */ }) {
        Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Localized Description")
    }
}

If control of when the tooltip is shown is desired please see

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AddCircle
import androidx.compose.material3.Icon
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val tooltipState = rememberTooltipState()
val scope = rememberCoroutineScope()
Column(horizontalAlignment = Alignment.CenterHorizontally) {
    TooltipBox(
        positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
        tooltip = { PlainTooltip { Text("Add to list") } },
        state = tooltipState
    ) {
        Icon(imageVector = Icons.Filled.AddCircle, contentDescription = "Localized Description")
    }
    Spacer(Modifier.requiredHeight(30.dp))
    OutlinedButton(onClick = { scope.launch { tooltipState.show() } }) {
        Text("Display tooltip")
    }
}

Plain tooltip with caret shown on long press:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState

TooltipBox(
    positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
    tooltip = {
        PlainTooltip(caretSize = TooltipDefaults.caretSize) { Text("Add to favorites") }
    },
    state = rememberTooltipState()
) {
    IconButton(onClick = { /* Icon button's click event */ }) {
        Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Localized Description")
    }
}

Plain tooltip shown on long press with a custom caret:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp

TooltipBox(
    positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
    tooltip = { PlainTooltip(caretSize = DpSize(24.dp, 12.dp)) { Text("Add to favorites") } },
    state = rememberTooltipState()
) {
    IconButton(onClick = { /* Icon button's click event */ }) {
        Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Localized Description")
    }
}

Tooltip that is invoked when the anchor is long pressed:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Info
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.RichTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.rememberCoroutineScope

val tooltipState = rememberTooltipState(isPersistent = true)
val scope = rememberCoroutineScope()
TooltipBox(
    positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
    tooltip = {
        RichTooltip(
            title = { Text(richTooltipSubheadText) },
            action = {
                TextButton(onClick = { scope.launch { tooltipState.dismiss() } }) {
                    Text(richTooltipActionText)
                }
            }
        ) {
            Text(richTooltipText)
        }
    },
    state = tooltipState
) {
    IconButton(onClick = { /* Icon button's click event */ }) {
        Icon(imageVector = Icons.Filled.Info, contentDescription = "Localized Description")
    }
}

If control of when the tooltip is shown is desired please see

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Info
import androidx.compose.material3.Icon
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.RichTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val tooltipState = rememberTooltipState(isPersistent = true)
val scope = rememberCoroutineScope()
Column(horizontalAlignment = Alignment.CenterHorizontally) {
    TooltipBox(
        positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
        tooltip = {
            RichTooltip(
                title = { Text(richTooltipSubheadText) },
                action = {
                    TextButton(onClick = { scope.launch { tooltipState.dismiss() } }) {
                        Text(richTooltipActionText)
                    }
                }
            ) {
                Text(richTooltipText)
            }
        },
        state = tooltipState
    ) {
        Icon(imageVector = Icons.Filled.Info, contentDescription = "Localized Description")
    }
    Spacer(Modifier.requiredHeight(30.dp))
    OutlinedButton(onClick = { scope.launch { tooltipState.show() } }) {
        Text("Display tooltip")
    }
}

Rich tooltip with caret shown on long press:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Info
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.RichTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.rememberCoroutineScope

val tooltipState = rememberTooltipState(isPersistent = true)
val scope = rememberCoroutineScope()
TooltipBox(
    positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
    tooltip = {
        RichTooltip(
            title = { Text(richTooltipSubheadText) },
            action = {
                TextButton(onClick = { scope.launch { tooltipState.dismiss() } }) {
                    Text(richTooltipActionText)
                }
            },
            caretSize = TooltipDefaults.caretSize
        ) {
            Text(richTooltipText)
        }
    },
    state = tooltipState
) {
    IconButton(onClick = { /* Icon button's click event */ }) {
        Icon(imageVector = Icons.Filled.Info, contentDescription = "Localized Description")
    }
}

Rich tooltip shown on long press with a custom caret

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Info
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.RichTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp

val tooltipState = rememberTooltipState(isPersistent = true)
val scope = rememberCoroutineScope()
TooltipBox(
    positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),
    tooltip = {
        RichTooltip(
            title = { Text(richTooltipSubheadText) },
            action = {
                TextButton(onClick = { scope.launch { tooltipState.dismiss() } }) {
                    Text(richTooltipActionText)
                }
            },
            caretSize = DpSize(32.dp, 16.dp)
        ) {
            Text(richTooltipText)
        }
    },
    state = tooltipState
) {
    IconButton(onClick = { /* Icon button's click event */ }) {
        Icon(imageVector = Icons.Filled.Info, contentDescription = "Localized Description")
    }
}
Parameters
positionProvider: PopupPositionProvider

PopupPositionProvider that will be used to place the tooltip relative to the anchor content.

tooltip: @Composable TooltipScope.() -> Unit

the composable that will be used to populate the tooltip's content.

state: TooltipState

handles the state of the tooltip's visibility.

modifier: Modifier = Modifier

the Modifier to be applied to the TooltipBox.

onDismissRequest: (() -> Unit)? = null

executes when the user clicks outside of the tooltip. By default, the tooltip will dismiss when it's being shown when a user clicks outside of the tooltip.

focusable: Boolean = true

Boolean that determines if the tooltip is focusable. When true, the tooltip will consume touch events while it's shown and will have accessibility focus move to the first element of the component. When false, the tooltip won't consume touch events while it's shown but assistive-tech users will need to swipe or drag to get to the first element of the component.

enableUserInput: Boolean = true

Boolean which determines if this TooltipBox will handle long press and mouse hover to trigger the tooltip through the state provided.

content: @Composable () -> Unit

the composable that the tooltip will anchor to.

TooltipState

@ExperimentalMaterial3Api
fun TooltipState(
    initialIsVisible: Boolean = false,
    isPersistent: Boolean = true,
    mutatorMutex: MutatorMutex = BasicTooltipDefaults.GlobalMutatorMutex
): TooltipState

Constructor extension function for TooltipState

Parameters
initialIsVisible: Boolean = false

the initial value for the tooltip's visibility when drawn.

isPersistent: Boolean = true

Boolean that determines if the tooltip associated with this will be persistent or not. If isPersistent is true, then the tooltip will only be dismissed when the user clicks outside the bounds of the tooltip or if TooltipState.dismiss is called. When isPersistent is false, the tooltip will dismiss after a short duration. Ideally, this should be set to true when there is actionable content being displayed within a tooltip.

mutatorMutex: MutatorMutex = BasicTooltipDefaults.GlobalMutatorMutex

MutatorMutex used to ensure that for all of the tooltips associated with the mutator mutex, only one will be shown on the screen at any time.

@ExperimentalMaterial3Api
@Composable
fun TopAppBar(
    title: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    navigationIcon: @Composable () -> Unit = {},
    actions: @Composable RowScope.() -> Unit = {},
    expandedHeight: Dp = TopAppBarDefaults.TopAppBarExpandedHeight,
    windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
    colors: TopAppBarColors = TopAppBarDefaults.topAppBarColors(),
    scrollBehavior: TopAppBarScrollBehavior? = null
): Unit

Material Design small top app bar.

Top app bars display information and actions at the top of a screen.

This small TopAppBar has slots for a title, navigation icon, and actions.

Small top app bar image

A simple top app bar looks like:

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp

Scaffold(
    topBar = {
        TopAppBar(
            title = {
                Text("Simple TopAppBar", maxLines = 1, overflow = TextOverflow.Ellipsis)
            },
            navigationIcon = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Menu,
                        contentDescription = "Localized description"
                    )
                }
            },
            actions = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Favorite,
                        contentDescription = "Localized description"
                    )
                }
            }
        )
    },
    content = { innerPadding ->
        LazyColumn(
            contentPadding = innerPadding,
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            val list = (0..75).map { it.toString() }
            items(count = list.size) {
                Text(
                    text = list[it],
                    style = MaterialTheme.typography.bodyLarge,
                    modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                )
            }
        }
    }
)

A top app bar that uses a scrollBehavior to customize its nested scrolling behavior when working in conjunction with a scrolling content looks like:

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp

val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    topBar = {
        TopAppBar(
            title = { Text("TopAppBar", maxLines = 1, overflow = TextOverflow.Ellipsis) },
            navigationIcon = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Menu,
                        contentDescription = "Localized description"
                    )
                }
            },
            actions = {
                // RowScope here, so these icons will be placed horizontally
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Favorite,
                        contentDescription = "Localized description"
                    )
                }
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Favorite,
                        contentDescription = "Localized description"
                    )
                }
            },
            scrollBehavior = scrollBehavior
        )
    },
    content = { innerPadding ->
        LazyColumn(
            contentPadding = innerPadding,
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            val list = (0..75).map { it.toString() }
            items(count = list.size) {
                Text(
                    text = list[it],
                    style = MaterialTheme.typography.bodyLarge,
                    modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                )
            }
        }
    }
)
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp

val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    topBar = {
        TopAppBar(
            title = { Text("TopAppBar", maxLines = 1, overflow = TextOverflow.Ellipsis) },
            subtitle = { Text("Subtitle", maxLines = 1, overflow = TextOverflow.Ellipsis) },
            navigationIcon = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Menu,
                        contentDescription = "Localized description"
                    )
                }
            },
            actions = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Favorite,
                        contentDescription = "Localized description"
                    )
                }
            },
            scrollBehavior = scrollBehavior
        )
    },
    content = { innerPadding ->
        LazyColumn(
            contentPadding = innerPadding,
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            val list = (0..75).map { it.toString() }
            items(count = list.size) {
                Text(
                    text = list[it],
                    style = MaterialTheme.typography.bodyLarge,
                    modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                )
            }
        }
    }
)
Parameters
title: @Composable () -> Unit

the title to be displayed in the top app bar

modifier: Modifier = Modifier

the Modifier to be applied to this top app bar

navigationIcon: @Composable () -> Unit = {}

the navigation icon displayed at the start of the top app bar. This should typically be an IconButton or IconToggleButton.

actions: @Composable RowScope.() -> Unit = {}

the actions displayed at the end of the top app bar. This should typically be IconButtons. The default layout here is a Row, so icons inside will be placed horizontally.

expandedHeight: Dp = TopAppBarDefaults.TopAppBarExpandedHeight

this app bar's height. When a specified scrollBehavior causes the app bar to collapse or expand, this value will represent the maximum height that the bar will be allowed to expand. This value must be specified and finite, otherwise it will be ignored and replaced with TopAppBarDefaults.TopAppBarExpandedHeight.

windowInsets: WindowInsets = TopAppBarDefaults.windowInsets

a window insets that app bar will respect.

colors: TopAppBarColors = TopAppBarDefaults.topAppBarColors()

TopAppBarColors that will be used to resolve the colors used for this top app bar in different states. See TopAppBarDefaults.topAppBarColors.

scrollBehavior: TopAppBarScrollBehavior? = null

a TopAppBarScrollBehavior which holds various offset values that will be applied by this top app bar to set up its height and colors. A scroll behavior is designed to work in conjunction with a scrolled content to change the top app bar appearance as the content scrolls. See TopAppBarScrollBehavior.nestedScrollConnection.

@ExperimentalMaterial3ExpressiveApi
@Composable
fun TopAppBar(
    title: @Composable () -> Unit,
    subtitle: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    navigationIcon: @Composable () -> Unit = {},
    actions: @Composable RowScope.() -> Unit = {},
    titleHorizontalAlignment: TopAppBarTitleAlignment = TopAppBarTitleAlignment.Start,
    expandedHeight: Dp = TopAppBarDefaults.TopAppBarExpandedHeight,
    windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
    colors: TopAppBarColors = TopAppBarDefaults.topAppBarColors(),
    scrollBehavior: TopAppBarScrollBehavior? = null
): Unit

Material Design small top app bar.

Top app bars display information and actions at the top of a screen.

This small TopAppBar has slots for a title, subtitle, navigation icon, and actions.

Small top app bar image

A top app bar that uses a scrollBehavior to customize its nested scrolling behavior when working in conjunction with a scrolling content looks like:

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp

val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    topBar = {
        TopAppBar(
            title = {
                Text("Simple TopAppBar", maxLines = 1, overflow = TextOverflow.Ellipsis)
            },
            subtitle = { Text("Subtitle", maxLines = 1, overflow = TextOverflow.Ellipsis) },
            navigationIcon = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Menu,
                        contentDescription = "Localized description"
                    )
                }
            },
            actions = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Favorite,
                        contentDescription = "Localized description"
                    )
                }
            },
            scrollBehavior = scrollBehavior
        )
    },
    content = { innerPadding ->
        LazyColumn(
            contentPadding = innerPadding,
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            val list = (0..75).map { it.toString() }
            items(count = list.size) {
                Text(
                    text = list[it],
                    style = MaterialTheme.typography.bodyLarge,
                    modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                )
            }
        }
    }
)
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarTitleAlignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp

val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    topBar = {
        TopAppBar(
            title = {
                Text("Simple TopAppBar", maxLines = 1, overflow = TextOverflow.Ellipsis)
            },
            subtitle = { Text("Subtitle", maxLines = 1, overflow = TextOverflow.Ellipsis) },
            titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
            navigationIcon = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Menu,
                        contentDescription = "Localized description"
                    )
                }
            },
            actions = {
                IconButton(onClick = { /* doSomething() */ }) {
                    Icon(
                        imageVector = Icons.Filled.Favorite,
                        contentDescription = "Localized description"
                    )
                }
            },
            scrollBehavior = scrollBehavior
        )
    },
    content = { innerPadding ->
        LazyColumn(
            contentPadding = innerPadding,
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            val list = (0..75).map { it.toString() }
            items(count = list.size) {
                Text(
                    text = list[it],
                    style = MaterialTheme.typography.bodyLarge,
                    modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                )
            }
        }
    }
)
Parameters
title: @Composable () -> Unit

the title to be displayed in the top app bar

subtitle: @Composable () -> Unit

the subtitle to be displayed in the top app bar

modifier: Modifier = Modifier

the Modifier to be applied to this top app bar

navigationIcon: @Composable () -> Unit = {}

the navigation icon displayed at the start of the top app bar. This should typically be an IconButton or IconToggleButton.

actions: @Composable RowScope.() -> Unit = {}

the actions displayed at the end of the top app bar. This should typically be IconButtons. The default layout here is a Row, so icons inside will be placed horizontally.

titleHorizontalAlignment: TopAppBarTitleAlignment = TopAppBarTitleAlignment.Start

the horizontal alignment of the title and subtitle

expandedHeight: Dp = TopAppBarDefaults.TopAppBarExpandedHeight

this app bar's height. When a specified scrollBehavior causes the app bar to collapse or expand, this value will represent the maximum height that the bar will be allowed to expand. This value must be specified and finite, otherwise it will be ignored and replaced with TopAppBarDefaults.TopAppBarExpandedHeight.

windowInsets: WindowInsets = TopAppBarDefaults.windowInsets

a window insets that app bar will respect.

colors: TopAppBarColors = TopAppBarDefaults.topAppBarColors()

TopAppBarColors that will be used to resolve the colors used for this top app bar in different states. See TopAppBarDefaults.topAppBarColors.

scrollBehavior: TopAppBarScrollBehavior? = null

a TopAppBarScrollBehavior which holds various offset values that will be applied by this top app bar to set up its height and colors. A scroll behavior is designed to work in conjunction with a scrolled content to change the top app bar appearance as the content scrolls. See TopAppBarScrollBehavior.nestedScrollConnection.

TriStateCheckbox

@Composable
fun TriStateCheckbox(
    state: ToggleableState,
    onClick: (() -> Unit)?,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: CheckboxColors = CheckboxDefaults.colors(),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design checkbox parent.

Checkboxes can have a parent-child relationship with other checkboxes. When the parent checkbox is checked, all child checkboxes are checked. If a parent checkbox is unchecked, all child checkboxes are unchecked. If some, but not all, child checkboxes are checked, the parent checkbox becomes an indeterminate checkbox.

Checkbox image

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.selection.toggleable
import androidx.compose.foundation.selection.triStateToggleable
import androidx.compose.material3.Checkbox
import androidx.compose.material3.Text
import androidx.compose.material3.TriStateCheckbox
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.state.ToggleableState
import androidx.compose.ui.unit.dp

Column {
    // define dependent checkboxes states
    val (state, onStateChange) = remember { mutableStateOf(true) }
    val (state2, onStateChange2) = remember { mutableStateOf(true) }

    // TriStateCheckbox state reflects state of dependent checkboxes
    val parentState =
        remember(state, state2) {
            if (state && state2) ToggleableState.On
            else if (!state && !state2) ToggleableState.Off else ToggleableState.Indeterminate
        }
    // click on TriStateCheckbox can set state for dependent checkboxes
    val onParentClick = {
        val s = parentState != ToggleableState.On
        onStateChange(s)
        onStateChange2(s)
    }

    // The sample below composes just basic checkboxes which are not fully accessible on their
    // own. See the CheckboxWithTextSample as a way to ensure your checkboxes are fully
    // accessible.
    Row(
        verticalAlignment = Alignment.CenterVertically,
        modifier =
            Modifier.triStateToggleable(
                state = parentState,
                onClick = onParentClick,
                role = Role.Checkbox
            )
    ) {
        TriStateCheckbox(
            state = parentState,
            onClick = null,
        )
        Text("Receive Emails")
    }
    Spacer(Modifier.size(25.dp))
    Column(Modifier.padding(24.dp, 0.dp, 0.dp, 0.dp)) {
        Row(
            verticalAlignment = Alignment.CenterVertically,
            modifier =
                Modifier.toggleable(
                    value = state,
                    onValueChange = onStateChange,
                    role = Role.Checkbox
                )
        ) {
            Checkbox(state, null)
            Text("Daily")
        }
        Spacer(Modifier.size(25.dp))
        Row(
            verticalAlignment = Alignment.CenterVertically,
            modifier =
                Modifier.toggleable(
                    value = state2,
                    onValueChange = onStateChange2,
                    role = Role.Checkbox
                )
        ) {
            Checkbox(state2, null)
            Text("Weekly")
        }
    }
}
Parameters
state: ToggleableState

whether this checkbox is checked, unchecked, or in an indeterminate state

onClick: (() -> Unit)?

called when this checkbox is clicked. If null, then this checkbox will not be interactable, unless something else handles its input events and updates its state.

modifier: Modifier = Modifier

the Modifier to be applied to this checkbox

enabled: Boolean = true

controls the enabled state of this checkbox. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

colors: CheckboxColors = CheckboxDefaults.colors()

CheckboxColors that will be used to resolve the colors used for this checkbox in different states. See CheckboxDefaults.colors.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this checkbox. You can use this to change the checkbox's appearance or preview the checkbox in different states. Note that if null is provided, interactions will still happen internally.

See also
Checkbox

if you want a simple component that represents Boolean state

VerticalDivider

@Composable
fun VerticalDivider(
    modifier: Modifier = Modifier,
    thickness: Dp = DividerDefaults.Thickness,
    color: Color = DividerDefaults.color
): Unit

Material Design divider.

A divider is a thin line that groups content in lists and layouts.

Divider image

Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this divider line.

thickness: Dp = DividerDefaults.Thickness

thickness of this divider line. Using Dp.Hairline will produce a single pixel divider regardless of screen density.

color: Color = DividerDefaults.color

color of this divider line.

VerticalDragHandle

@Composable
fun VerticalDragHandle(
    modifier: Modifier = Modifier,
    sizes: DragHandleSizes = VerticalDragHandleDefaults.Sizes,
    colors: DragHandleColors = VerticalDragHandleDefaults.colors(),
    shapes: DragHandleShapes = VerticalDragHandleDefaults.shapes(),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design Drag Handle.

A drag handle is a capsule-like shape that can be used by users to change component size and/or position by dragging. A typical usage of it will be pane expansion - when you split your screen into multiple panes, a drag handle is suggested to be used so users can drag it to change the proportion of how the screen is being split. Note that a vertically oriented drag handle is meant to convey horizontal drag motions.

Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this drag handle.

sizes: DragHandleSizes = VerticalDragHandleDefaults.Sizes

sizes of this drag handle; see VerticalDragHandleDefaults.sizes for the default values.

colors: DragHandleColors = VerticalDragHandleDefaults.colors()

colors of this drag handle; see VerticalDragHandleDefaults.colors for the default values.

shapes: DragHandleShapes = VerticalDragHandleDefaults.shapes()

shapes of this drag handle; see VerticalDragHandleDefaults.colors for the default values.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this drag handle. You can use this to change the drag handle's appearance or preview the drag handle in different states. Note that if null is provided, interactions will still happen internally.

VerticalFloatingAppBar

@ExperimentalMaterial3ExpressiveApi
@Composable
fun VerticalFloatingAppBar(
    expanded: Boolean,
    modifier: Modifier = Modifier,
    containerColor: Color = FloatingAppBarDefaults.ContainerColor,
    contentPadding: PaddingValues = FloatingAppBarDefaults.ContentPadding,
    scrollBehavior: FloatingAppBarScrollBehavior? = null,
    shape: Shape = FloatingAppBarDefaults.ContainerShape,
    leadingContent: (@Composable ColumnScope.() -> Unit)? = null,
    trailingContent: (@Composable ColumnScope.() -> Unit)? = null,
    content: @Composable ColumnScope.() -> Unit
): Unit
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.FloatingAppBarDefaults.ScreenOffset
import androidx.compose.material3.FloatingAppBarExitDirection.Companion.End
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.VerticalFloatingAppBar
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment.Companion.CenterEnd
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp

val context = LocalContext.current
val isTouchExplorationEnabled = remember {
    val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
    am.isEnabled && am.isTouchExplorationEnabled
}
val listState = rememberLazyListState()
var currentItem = 0
val expanded by remember {
    derivedStateOf {
        val temp = currentItem
        currentItem = listState.firstVisibleItemIndex
        listState.firstVisibleItemIndex <= temp // true if the list is scrolled up
    }
}
Scaffold(
    content = { innerPadding ->
        Box {
            LazyColumn(
                state = listState,
                contentPadding = innerPadding,
                verticalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                val list = (0..75).map { it.toString() }
                items(count = list.size) {
                    Text(
                        text = list[it],
                        style = MaterialTheme.typography.bodyLarge,
                        modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                    )
                }
            }
            VerticalFloatingAppBar(
                modifier = Modifier.align(CenterEnd).offset(x = -ScreenOffset),
                expanded = expanded || isTouchExplorationEnabled,
                leadingContent = { leadingContent() },
                trailingContent = { trailingContent() },
                content = {
                    FilledIconButton(
                        modifier = Modifier.height(64.dp),
                        onClick = { /* doSomething() */ }
                    ) {
                        Icon(Icons.Filled.Add, contentDescription = "Localized description")
                    }
                },
            )
        }
    }
)
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.FloatingAppBarDefaults
import androidx.compose.material3.FloatingAppBarDefaults.ScreenOffset
import androidx.compose.material3.FloatingAppBarExitDirection.Companion.End
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.VerticalFloatingAppBar
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment.Companion.CenterEnd
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp

val context = LocalContext.current
val isTouchExplorationEnabled = remember {
    val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
    am.isEnabled && am.isTouchExplorationEnabled
}
val listState = rememberLazyListState()
val exitAlwaysScrollBehavior =
    FloatingAppBarDefaults.exitAlwaysScrollBehavior(exitDirection = End)
Scaffold(
    modifier = Modifier.nestedScroll(exitAlwaysScrollBehavior),
    content = { innerPadding ->
        Box {
            LazyColumn(
                state = listState,
                contentPadding = innerPadding,
                verticalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                val list = (0..75).map { it.toString() }
                items(count = list.size) {
                    Text(
                        text = list[it],
                        style = MaterialTheme.typography.bodyLarge,
                        modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                    )
                }
            }
            VerticalFloatingAppBar(
                modifier = Modifier.align(CenterEnd).offset(x = -ScreenOffset),
                expanded = true,
                leadingContent = { leadingContent() },
                trailingContent = { trailingContent() },
                content = {
                    FilledIconButton(
                        modifier = Modifier.height(64.dp),
                        onClick = { /* doSomething() */ }
                    ) {
                        Icon(Icons.Filled.Add, contentDescription = "Localized description")
                    }
                },
                scrollBehavior =
                    if (!isTouchExplorationEnabled) exitAlwaysScrollBehavior else null,
            )
        }
    }
)
Parameters
expanded: Boolean

whether the FloatingAppBar is in expanded mode, i.e. showing leadingContent and trailingContent.

modifier: Modifier = Modifier

the Modifier to be applied to this FloatingAppBar.

containerColor: Color = FloatingAppBarDefaults.ContainerColor

the color used for the background of this FloatingAppBar. Use Color.Transparent] to have no color.

contentPadding: PaddingValues = FloatingAppBarDefaults.ContentPadding

the padding applied to the content of this FloatingAppBar.

scrollBehavior: FloatingAppBarScrollBehavior? = null

a FloatingAppBarScrollBehavior. If null, this FloatingAppBar will not automatically react to scrolling.

shape: Shape = FloatingAppBarDefaults.ContainerShape

the shape used for this FloatingAppBar.

leadingContent: (@Composable ColumnScope.() -> Unit)? = null

the leading content of this FloatingAppBar. The default layout here is a Column, so content inside will be placed vertically. Only showing if expanded is true.

trailingContent: (@Composable ColumnScope.() -> Unit)? = null

the trailing content of this FloatingAppBar. The default layout here is a Column, so content inside will be placed vertically. Only showing if expanded is true.

content: @Composable ColumnScope.() -> Unit

the main content of this FloatingAppBar. The default layout here is a Column, so content inside will be placed vertically.

WideNavigationRail

@ExperimentalMaterial3ExpressiveApi
@Composable
fun WideNavigationRail(
    modifier: Modifier = Modifier,
    state: WideNavigationRailState = rememberWideNavigationRailState(),
    shape: Shape = WideNavigationRailDefaults.containerShape,
    colors: WideNavigationRailColors = WideNavigationRailDefaults.colors(),
    header: (@Composable () -> Unit)? = null,
    windowInsets: WindowInsets = WideNavigationRailDefaults.windowInsets,
    arrangement: WideNavigationRailArrangement = WideNavigationRailDefaults.Arrangement,
    content: @Composable () -> Unit
): Unit

Material design wide navigation rail.

Wide navigation rails provide access to primary destinations in apps when using tablet and desktop screens.

The wide navigation rail should be used to display multiple WideNavigationRailItems, each representing a singular app destination, and, optionally, a header containing a menu button, a FloatingActionButton, and/or a logo. Each destination is typically represented by an icon and a text label.

The WideNavigationRail is collapsed by default, but it also supports being expanded via a WideNavigationRailState. When collapsed, the rail should display three to seven navigation items. A simple example looks like:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Star
import androidx.compose.material.icons.outlined.FavoriteBorder
import androidx.compose.material.icons.outlined.Home
import androidx.compose.material.icons.outlined.StarBorder
import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationRail
import androidx.compose.material3.NavigationRailItem
import androidx.compose.material3.Text
import androidx.compose.material3.WideNavigationRail
import androidx.compose.material3.WideNavigationRailItem
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember

var selectedItem by remember { mutableIntStateOf(0) }
val items = listOf("Home", "Search", "Settings")
val selectedIcons = listOf(Icons.Filled.Home, Icons.Filled.Favorite, Icons.Filled.Star)
val unselectedIcons =
    listOf(Icons.Outlined.Home, Icons.Outlined.FavoriteBorder, Icons.Outlined.StarBorder)
WideNavigationRail {
    items.forEachIndexed { index, item ->
        WideNavigationRailItem(
            icon = {
                Icon(
                    if (selectedItem == index) selectedIcons[index] else unselectedIcons[index],
                    contentDescription = null
                )
            },
            label = { Text(item) },
            selected = selectedItem == index,
            onClick = { selectedItem = index }
        )
    }
}

When expanded, the rail should display at least three navigation items. A simple example looks like:

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Star
import androidx.compose.material.icons.outlined.FavoriteBorder
import androidx.compose.material.icons.outlined.Home
import androidx.compose.material.icons.outlined.StarBorder
import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationRail
import androidx.compose.material3.NavigationRailItem
import androidx.compose.material3.Text
import androidx.compose.material3.WideNavigationRail
import androidx.compose.material3.WideNavigationRailItem
import androidx.compose.material3.rememberWideNavigationRailState
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember

var selectedItem by remember { mutableIntStateOf(0) }
val items = listOf("Home", "Search", "Settings")
val selectedIcons = listOf(Icons.Filled.Home, Icons.Filled.Favorite, Icons.Filled.Star)
val unselectedIcons =
    listOf(Icons.Outlined.Home, Icons.Outlined.FavoriteBorder, Icons.Outlined.StarBorder)
WideNavigationRail(state = rememberWideNavigationRailState()) {
    items.forEachIndexed { index, item ->
        WideNavigationRailItem(
            railExpanded = true,
            icon = {
                Icon(
                    if (selectedItem == index) selectedIcons[index] else unselectedIcons[index],
                    contentDescription = null
                )
            },
            label = { Text(item) },
            selected = selectedItem == index,
            onClick = { selectedItem = index }
        )
    }
}

The WideNavigationRail also supports automatically animating between the collapsed and expanded values. That can be done like so:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.MenuOpen
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.icons.filled.Star
import androidx.compose.material.icons.outlined.FavoriteBorder
import androidx.compose.material.icons.outlined.Home
import androidx.compose.material.icons.outlined.StarBorder
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.NavigationRail
import androidx.compose.material3.NavigationRailItem
import androidx.compose.material3.Text
import androidx.compose.material3.WideNavigationRail
import androidx.compose.material3.WideNavigationRailItem
import androidx.compose.material3.WideNavigationRailValue
import androidx.compose.material3.rememberWideNavigationRailState
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.stateDescription
import androidx.compose.ui.unit.dp

var selectedItem by remember { mutableIntStateOf(0) }
val items = listOf("Home", "Search", "Settings")
val selectedIcons = listOf(Icons.Filled.Home, Icons.Filled.Favorite, Icons.Filled.Star)
val unselectedIcons =
    listOf(Icons.Outlined.Home, Icons.Outlined.FavoriteBorder, Icons.Outlined.StarBorder)
val state = rememberWideNavigationRailState()
val scope = rememberCoroutineScope()

Row(Modifier.fillMaxWidth()) {
    WideNavigationRail(
        state = state,
        header = {
            IconButton(
                modifier =
                    Modifier.padding(start = 24.dp).semantics {
                        // The button must announce the expanded or collapsed state of the rail
                        // for accessibility.
                        stateDescription =
                            if (state.currentValue == WideNavigationRailValue.Expanded) {
                                "Expanded"
                            } else {
                                "Collapsed"
                            }
                    },
                onClick = {
                    scope.launch {
                        if (state.targetValue == WideNavigationRailValue.Expanded)
                            state.collapse()
                        else state.expand()
                    }
                }
            ) {
                if (state.targetValue == WideNavigationRailValue.Expanded) {
                    Icon(Icons.AutoMirrored.Filled.MenuOpen, "Collapse rail")
                } else {
                    Icon(Icons.Filled.Menu, "Expand rail")
                }
            }
        }
    ) {
        items.forEachIndexed { index, item ->
            WideNavigationRailItem(
                railExpanded = state.targetValue == WideNavigationRailValue.Expanded,
                icon = {
                    val imageVector =
                        if (selectedItem == index) {
                            selectedIcons[index]
                        } else {
                            unselectedIcons[index]
                        }
                    Icon(imageVector = imageVector, contentDescription = null)
                },
                label = { Text(item) },
                selected = selectedItem == index,
                onClick = { selectedItem = index }
            )
        }
    }

    val textString =
        if (state.currentValue == WideNavigationRailValue.Expanded) {
            "Expanded"
        } else {
            "Collapsed"
        }
    Column {
        Text(modifier = Modifier.padding(16.dp), text = "Is animating: " + state.isAnimating)
        Text(modifier = Modifier.padding(16.dp), text = "The rail is $textString.")
        Text(
            modifier = Modifier.padding(16.dp),
            text =
                "Note: The orientation of this demo has been locked to portrait mode, because" +
                    " landscape mode may result in a compact height in certain devices. For" +
                    " any compact screen dimensions, use a Navigation Bar instead."
        )
    }
}

// Lock the orientation for this demo as the navigation rail may look cut off in landscape in
// smaller screens.
val context = LocalContext.current
DisposableEffect(context) {
    (context as? Activity)?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
    onDispose {
        (context as? Activity)?.requestedOrientation =
            ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
    }
}

For a modal variation of the wide navigation rail, see ModalWideNavigationRail.

Finally, the WideNavigationRail supports setting a WideNavigationRailArrangement for the items, so that the items can be grouped at the top (the default), at the middle, or at the bottom of the rail. The header will always be at the top.

See WideNavigationRailItem for configuration specific to each item, and not the overall WideNavigationRail component.

Parameters
modifier: Modifier = Modifier

the Modifier to be applied to this wide navigation rail

state: WideNavigationRailState = rememberWideNavigationRailState()

the WideNavigationRailState of this wide navigation rail

shape: Shape = WideNavigationRailDefaults.containerShape

defines the shape of this wide navigation rail's container.

colors: WideNavigationRailColors = WideNavigationRailDefaults.colors()

WideNavigationRailColors that will be used to resolve the colors used for this wide navigation rail. See WideNavigationRailDefaults.colors

header: (@Composable () -> Unit)? = null

optional header that may hold a FloatingActionButton or a logo

windowInsets: WindowInsets = WideNavigationRailDefaults.windowInsets

a window insets of the wide navigation rail

arrangement: WideNavigationRailArrangement = WideNavigationRailDefaults.Arrangement

the WideNavigationRailArrangement of this wide navigation rail

content: @Composable () -> Unit

the content of this wide navigation rail, typically WideNavigationRailItems

WideNavigationRailItem

@ExperimentalMaterial3ExpressiveApi
@Composable
fun WideNavigationRailItem(
    selected: Boolean,
    onClick: () -> Unit,
    icon: @Composable () -> Unit,
    label: (@Composable () -> Unit)?,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    railExpanded: Boolean = false,
    iconPosition: NavigationItemIconPosition = WideNavigationRailItemDefaults.iconPositionFor(railExpanded),
    colors: NavigationItemColors = WideNavigationRailItemDefaults.colors(),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design wide navigation rail item.

It's recommend for navigation items to always have a text label. A WideNavigationRailItem always displays labels (if they exist) when selected and unselected.

The WideNavigationRailItem supports two different icon positions, top and start, which is controlled by the iconPosition param:

  • If the icon position is NavigationItemIconPosition.Top the icon will be displayed above the label. This configuration should be used with collapsed wide navigation rails.

  • If the icon position is NavigationItemIconPosition.Start the icon will be displayed to the start of the label. This configuration should be used with expanded wide navigation rails.

However, if an animated item is desired, the iconPosition can be controlled via the expanded value of the associated WideNavigationRail or ModalWideNavigationRail. By default, it'll use the railExpanded to follow the configuration described above.

Parameters
selected: Boolean

whether this item is selected

onClick: () -> Unit

called when this item is clicked

icon: @Composable () -> Unit

icon for this item, typically an Icon

label: (@Composable () -> Unit)?

text label for this item

modifier: Modifier = Modifier

the Modifier to be applied to this item

enabled: Boolean = true

controls the enabled state of this item. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

railExpanded: Boolean = false

whether the associated WideNavigationRail is expanded or collapsed

iconPosition: NavigationItemIconPosition = WideNavigationRailItemDefaults.iconPositionFor(railExpanded)

the NavigationItemIconPosition for the icon

colors: NavigationItemColors = WideNavigationRailItemDefaults.colors()

NavigationItemColors that will be used to resolve the colors used for this item in different states. See WideNavigationRailItemDefaults.colors

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this item. You can use this to change the item's appearance or preview the item in different states. Note that if null is provided, interactions will still happen internally.

contentColorFor

@Composable
fun contentColorFor(backgroundColor: Color): Color

The Material color system contains pairs of colors that are typically used for the background and content color inside a component. For example, a Button typically uses primary for its background, and onPrimary for the color of its content (usually text or iconography).

This function tries to match the provided backgroundColor to a 'background' color in this ColorScheme, and then will return the corresponding color used for content. For example, when backgroundColor is ColorScheme.primary, this will return ColorScheme.onPrimary.

If backgroundColor does not match a background color in the theme, this will return the current value of LocalContentColor as a best-effort color.

Returns
Color

the matching content color for backgroundColor. If backgroundColor is not present in the theme's ColorScheme, then returns the current value of LocalContentColor.

See also
contentColorFor

darkColorScheme

fun darkColorScheme(
    primary: Color = ColorDarkTokens.Primary,
    onPrimary: Color = ColorDarkTokens.OnPrimary,
    primaryContainer: Color = ColorDarkTokens.PrimaryContainer,
    onPrimaryContainer: Color = ColorDarkTokens.OnPrimaryContainer,
    inversePrimary: Color = ColorDarkTokens.InversePrimary,
    secondary: Color = ColorDarkTokens.Secondary,
    onSecondary: Color = ColorDarkTokens.OnSecondary,
    secondaryContainer: Color = ColorDarkTokens.SecondaryContainer,
    onSecondaryContainer: Color = ColorDarkTokens.OnSecondaryContainer,
    tertiary: Color = ColorDarkTokens.Tertiary,
    onTertiary: Color = ColorDarkTokens.OnTertiary,
    tertiaryContainer: Color = ColorDarkTokens.TertiaryContainer,
    onTertiaryContainer: Color = ColorDarkTokens.OnTertiaryContainer,
    background: Color = ColorDarkTokens.Background,
    onBackground: Color = ColorDarkTokens.OnBackground,
    surface: Color = ColorDarkTokens.Surface,
    onSurface: Color = ColorDarkTokens.OnSurface,
    surfaceVariant: Color = ColorDarkTokens.SurfaceVariant,
    onSurfaceVariant: Color = ColorDarkTokens.OnSurfaceVariant,
    surfaceTint: Color = primary,
    inverseSurface: Color = ColorDarkTokens.InverseSurface,
    inverseOnSurface: Color = ColorDarkTokens.InverseOnSurface,
    error: Color = ColorDarkTokens.Error,
    onError: Color = ColorDarkTokens.OnError,
    errorContainer: Color = ColorDarkTokens.ErrorContainer,
    onErrorContainer: Color = ColorDarkTokens.OnErrorContainer,
    outline: Color = ColorDarkTokens.Outline,
    outlineVariant: Color = ColorDarkTokens.OutlineVariant,
    scrim: Color = ColorDarkTokens.Scrim,
    surfaceBright: Color = ColorDarkTokens.SurfaceBright,
    surfaceContainer: Color = ColorDarkTokens.SurfaceContainer,
    surfaceContainerHigh: Color = ColorDarkTokens.SurfaceContainerHigh,
    surfaceContainerHighest: Color = ColorDarkTokens.SurfaceContainerHighest,
    surfaceContainerLow: Color = ColorDarkTokens.SurfaceContainerLow,
    surfaceContainerLowest: Color = ColorDarkTokens.SurfaceContainerLowest,
    surfaceDim: Color = ColorDarkTokens.SurfaceDim
): ColorScheme

Returns a dark Material color scheme.

dynamicDarkColorScheme

@RequiresApi(value = 31)
fun dynamicDarkColorScheme(context: Context): ColorScheme

Creates a dark dynamic color scheme.

Use this function to create a color scheme based off the system wallpaper. If the developer changes the wallpaper this color scheme will change accordingly. This dynamic scheme is a dark theme variant.

Parameters
context: Context

The context required to get system resource data.

dynamicLightColorScheme

@RequiresApi(value = 31)
fun dynamicLightColorScheme(context: Context): ColorScheme

Creates a light dynamic color scheme.

Use this function to create a color scheme based off the system wallpaper. If the developer changes the wallpaper this color scheme will change accordingly. This dynamic scheme is a light theme variant.

Parameters
context: Context

The context required to get system resource data.

expressiveLightColorScheme

@ExperimentalMaterial3ExpressiveApi
fun expressiveLightColorScheme(): ColorScheme

Returns a light Material color scheme.

The default color scheme for MaterialExpressiveTheme. For dark mode, use darkColorScheme.

Example of MaterialExpressiveTheme toggling expressiveLightColorScheme and darkTheme.

import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialExpressiveTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.expressiveLightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color

@Composable
fun MyMaterialTheme(content: @Composable () -> Unit) {
    MaterialExpressiveTheme(
        colorScheme =
            if (isSystemInDarkTheme()) darkColorScheme() else expressiveLightColorScheme()
    ) {
        content()
    }
}

lightColorScheme

fun lightColorScheme(
    primary: Color = ColorLightTokens.Primary,
    onPrimary: Color = ColorLightTokens.OnPrimary,
    primaryContainer: Color = ColorLightTokens.PrimaryContainer,
    onPrimaryContainer: Color = ColorLightTokens.OnPrimaryContainer,
    inversePrimary: Color = ColorLightTokens.InversePrimary,
    secondary: Color = ColorLightTokens.Secondary,
    onSecondary: Color = ColorLightTokens.OnSecondary,
    secondaryContainer: Color = ColorLightTokens.SecondaryContainer,
    onSecondaryContainer: Color = ColorLightTokens.OnSecondaryContainer,
    tertiary: Color = ColorLightTokens.Tertiary,
    onTertiary: Color = ColorLightTokens.OnTertiary,
    tertiaryContainer: Color = ColorLightTokens.TertiaryContainer,
    onTertiaryContainer: Color = ColorLightTokens.OnTertiaryContainer,
    background: Color = ColorLightTokens.Background,
    onBackground: Color = ColorLightTokens.OnBackground,
    surface: Color = ColorLightTokens.Surface,
    onSurface: Color = ColorLightTokens.OnSurface,
    surfaceVariant: Color = ColorLightTokens.SurfaceVariant,
    onSurfaceVariant: Color = ColorLightTokens.OnSurfaceVariant,
    surfaceTint: Color = primary,
    inverseSurface: Color = ColorLightTokens.InverseSurface,
    inverseOnSurface: Color = ColorLightTokens.InverseOnSurface,
    error: Color = ColorLightTokens.Error,
    onError: Color = ColorLightTokens.OnError,
    errorContainer: Color = ColorLightTokens.ErrorContainer,
    onErrorContainer: Color = ColorLightTokens.OnErrorContainer,
    outline: Color = ColorLightTokens.Outline,
    outlineVariant: Color = ColorLightTokens.OutlineVariant,
    scrim: Color = ColorLightTokens.Scrim,
    surfaceBright: Color = ColorLightTokens.SurfaceBright,
    surfaceContainer: Color = ColorLightTokens.SurfaceContainer,
    surfaceContainerHigh: Color = ColorLightTokens.SurfaceContainerHigh,
    surfaceContainerHighest: Color = ColorLightTokens.SurfaceContainerHighest,
    surfaceContainerLow: Color = ColorLightTokens.SurfaceContainerLow,
    surfaceContainerLowest: Color = ColorLightTokens.SurfaceContainerLowest,
    surfaceDim: Color = ColorLightTokens.SurfaceDim
): ColorScheme

Returns a light Material color scheme.

rememberBottomAppBarState

@ExperimentalMaterial3Api
@Composable
fun rememberBottomAppBarState(
    initialHeightOffsetLimit: Float = -Float.MAX_VALUE,
    initialHeightOffset: Float = 0.0f,
    initialContentOffset: Float = 0.0f
): BottomAppBarState

Creates a BottomAppBarState that is remembered across compositions.

Parameters
initialHeightOffsetLimit: Float = -Float.MAX_VALUE

the initial value for BottomAppBarState.heightOffsetLimit, which represents the pixel limit that a bottom app bar is allowed to collapse when the scrollable content is scrolled

initialHeightOffset: Float = 0.0f

the initial value for BottomAppBarState.heightOffset. The initial offset height offset should be between zero and initialHeightOffsetLimit.

initialContentOffset: Float = 0.0f

the initial value for BottomAppBarState.contentOffset

rememberBottomSheetScaffoldState

@Composable
@ExperimentalMaterial3Api
fun rememberBottomSheetScaffoldState(
    bottomSheetState: SheetState = rememberStandardBottomSheetState(),
    snackbarHostState: SnackbarHostState = remember { SnackbarHostState() }
): BottomSheetScaffoldState

Create and remember a BottomSheetScaffoldState.

Parameters
bottomSheetState: SheetState = rememberStandardBottomSheetState()

the state of the standard bottom sheet. See rememberStandardBottomSheetState

snackbarHostState: SnackbarHostState = remember { SnackbarHostState() }

the SnackbarHostState used to show snackbars inside the scaffold

rememberDatePickerState

@Composable
@ExperimentalMaterial3Api
fun rememberDatePickerState(
    initialSelectedDateMillis: Long? = null,
    initialDisplayedMonthMillis: Long? = initialSelectedDateMillis,
    yearRange: IntRange = DatePickerDefaults.YearRange,
    initialDisplayMode: DisplayMode = DisplayMode.Picker,
    selectableDates: SelectableDates = DatePickerDefaults.AllDates
): DatePickerState

Creates a DatePickerState for a DatePicker that is remembered across compositions.

To create a date picker state outside composition, see the DatePickerState function.

Parameters
initialSelectedDateMillis: Long? = null

timestamp in UTC milliseconds from the epoch that represents an initial selection of a date. Provide a null to indicate no selection.

initialDisplayedMonthMillis: Long? = initialSelectedDateMillis

timestamp in UTC milliseconds from the epoch that represents an initial selection of a month to be displayed to the user. By default, in case an initialSelectedDateMillis is provided, the initial displayed month would be the month of the selected date. Otherwise, in case null is provided, the displayed month would be the current one.

yearRange: IntRange = DatePickerDefaults.YearRange

an IntRange that holds the year range that the date picker will be limited to

initialDisplayMode: DisplayMode = DisplayMode.Picker

an initial DisplayMode that this state will hold

selectableDates: SelectableDates = DatePickerDefaults.AllDates

a SelectableDates that is consulted to check if a date is allowed. In case a date is not allowed to be selected, it will appear disabled in the UI.

rememberDateRangePickerState

@Composable
@ExperimentalMaterial3Api
fun rememberDateRangePickerState(
    initialSelectedStartDateMillis: Long? = null,
    initialSelectedEndDateMillis: Long? = null,
    initialDisplayedMonthMillis: Long? = initialSelectedStartDateMillis,
    yearRange: IntRange = DatePickerDefaults.YearRange,
    initialDisplayMode: DisplayMode = DisplayMode.Picker,
    selectableDates: SelectableDates = DatePickerDefaults.AllDates
): DateRangePickerState

Creates a DateRangePickerState for a DateRangePicker that is remembered across compositions.

To create a date range picker state outside composition, see the DateRangePickerState function.

Parameters
initialSelectedStartDateMillis: Long? = null

timestamp in UTC milliseconds from the epoch that represents an initial selection of a start date. Provide a null to indicate no selection.

initialSelectedEndDateMillis: Long? = null

timestamp in UTC milliseconds from the epoch that represents an initial selection of an end date. Provide a null to indicate no selection.

initialDisplayedMonthMillis: Long? = initialSelectedStartDateMillis

timestamp in UTC milliseconds from the epoch that represents an initial selection of a month to be displayed to the user. By default, in case an initialSelectedStartDateMillis is provided, the initial displayed month would be the month of the selected date. Otherwise, in case null is provided, the displayed month would be the current one.

yearRange: IntRange = DatePickerDefaults.YearRange

an IntRange that holds the year range that the date range picker will be limited to

initialDisplayMode: DisplayMode = DisplayMode.Picker

an initial DisplayMode that this state will hold

selectableDates: SelectableDates = DatePickerDefaults.AllDates

a SelectableDates that is consulted to check if a date is allowed. In case a date is not allowed to be selected, it will appear disabled in the UI.

rememberDrawerState

@Composable
fun rememberDrawerState(
    initialValue: DrawerValue,
    confirmStateChange: (DrawerValue) -> Boolean = { true }
): DrawerState

Create and remember a DrawerState.

Parameters
initialValue: DrawerValue

The initial value of the state.

confirmStateChange: (DrawerValue) -> Boolean = { true }

Optional callback invoked to confirm or veto a pending state change.

rememberFloatingAppBarState

@ExperimentalMaterial3ExpressiveApi
@Composable
fun rememberFloatingAppBarState(
    initialOffsetLimit: Float = -Float.MAX_VALUE,
    initialOffset: Float = 0.0f,
    initialContentOffset: Float = 0.0f
): FloatingAppBarState

Creates a FloatingAppBarState that is remembered across compositions.

Parameters
initialOffsetLimit: Float = -Float.MAX_VALUE

the initial value for FloatingAppBarState.offsetLimit, which represents the pixel limit that a floating app bar is allowed to collapse when the scrollable content is scrolled.

initialOffset: Float = 0.0f

the initial value for FloatingAppBarState.offset. The initial offset should be between zero and initialOffsetLimit.

initialContentOffset: Float = 0.0f

the initial value for FloatingAppBarState.contentOffset

rememberModalBottomSheetState

@Composable
@ExperimentalMaterial3Api
fun rememberModalBottomSheetState(
    skipPartiallyExpanded: Boolean = false,
    confirmValueChange: (SheetValue) -> Boolean = { true }
): SheetState

Create and remember a SheetState for ModalBottomSheet.

Parameters
skipPartiallyExpanded: Boolean = false

Whether the partially expanded state, if the sheet is tall enough, should be skipped. If true, the sheet will always expand to the Expanded state and move to the Hidden state when hiding the sheet, either programmatically or by user interaction.

confirmValueChange: (SheetValue) -> Boolean = { true }

Optional callback invoked to confirm or veto a pending state change.

rememberStandardBottomSheetState

@Composable
@ExperimentalMaterial3Api
fun rememberStandardBottomSheetState(
    initialValue: SheetValue = PartiallyExpanded,
    confirmValueChange: (SheetValue) -> Boolean = { true },
    skipHiddenState: Boolean = true
): SheetState

Create and remember a SheetState for BottomSheetScaffold.

Parameters
initialValue: SheetValue = PartiallyExpanded

the initial value of the state. Should be either PartiallyExpanded or Expanded if skipHiddenState is true

confirmValueChange: (SheetValue) -> Boolean = { true }

optional callback invoked to confirm or veto a pending state change

skipHiddenState: Boolean = true

whether Hidden state is skipped for BottomSheetScaffold

rememberSwipeToDismissBoxState

@Composable
fun rememberSwipeToDismissBoxState(
    initialValue: SwipeToDismissBoxValue = SwipeToDismissBoxValue.Settled,
    confirmValueChange: (SwipeToDismissBoxValue) -> Boolean = { true },
    positionalThreshold: (totalDistance: Float) -> Float = SwipeToDismissBoxDefaults.positionalThreshold
): SwipeToDismissBoxState

Create and remember a SwipeToDismissBoxState.

Parameters
initialValue: SwipeToDismissBoxValue = SwipeToDismissBoxValue.Settled

The initial value of the state.

confirmValueChange: (SwipeToDismissBoxValue) -> Boolean = { true }

Optional callback invoked to confirm or veto a pending state change.

positionalThreshold: (totalDistance: Float) -> Float = SwipeToDismissBoxDefaults.positionalThreshold

The positional threshold to be used when calculating the target state while a swipe is in progress and when settling after the swipe ends. This is the distance from the start of a transition. It will be, depending on the direction of the interaction, added or subtracted from/to the origin offset. It should always be a positive value.

rememberTimePickerState

@Composable
@ExperimentalMaterial3Api
fun rememberTimePickerState(
    initialHour: Int = 0,
    initialMinute: Int = 0,
    is24Hour: Boolean = is24HourFormat
): TimePickerState

Creates a TimePickerState for a time picker that is remembered across compositions and configuration changes.

Parameters
initialHour: Int = 0

starting hour for this state, will be displayed in the time picker when launched. Ranges from 0 to 23

initialMinute: Int = 0

starting minute for this state, will be displayed in the time picker when launched. Ranges from 0 to 59

is24Hour: Boolean = is24HourFormat

The format for this time picker. false for 12 hour format with an AM/PM toggle or true for 24 hour format without toggle. Defaults to follow system setting.

rememberTooltipState

@Composable
@ExperimentalMaterial3Api
fun rememberTooltipState(
    initialIsVisible: Boolean = false,
    isPersistent: Boolean = false,
    mutatorMutex: MutatorMutex = BasicTooltipDefaults.GlobalMutatorMutex
): TooltipState

Create and remember the default TooltipState for TooltipBox.

Parameters
initialIsVisible: Boolean = false

the initial value for the tooltip's visibility when drawn.

isPersistent: Boolean = false

Boolean that determines if the tooltip associated with this will be persistent or not. If isPersistent is true, then the tooltip will only be dismissed when the user clicks outside the bounds of the tooltip or if TooltipState.dismiss is called. When isPersistent is false, the tooltip will dismiss after a short duration. Ideally, this should be set to true when there is actionable content being displayed within a tooltip.

mutatorMutex: MutatorMutex = BasicTooltipDefaults.GlobalMutatorMutex

MutatorMutex used to ensure that for all of the tooltips associated with the mutator mutex, only one will be shown on the screen at any time.

rememberTopAppBarState

@ExperimentalMaterial3Api
@Composable
fun rememberTopAppBarState(
    initialHeightOffsetLimit: Float = -Float.MAX_VALUE,
    initialHeightOffset: Float = 0.0f,
    initialContentOffset: Float = 0.0f
): TopAppBarState

Creates a TopAppBarState that is remembered across compositions.

Parameters
initialHeightOffsetLimit: Float = -Float.MAX_VALUE

the initial value for TopAppBarState.heightOffsetLimit, which represents the pixel limit that a top app bar is allowed to collapse when the scrollable content is scrolled

initialHeightOffset: Float = 0.0f

the initial value for TopAppBarState.heightOffset. The initial offset height offset should be between zero and initialHeightOffsetLimit.

initialContentOffset: Float = 0.0f

the initial value for TopAppBarState.contentOffset

rememberWideNavigationRailState

@ExperimentalMaterial3ExpressiveApi
@Composable
fun rememberWideNavigationRailState(
    initialValue: WideNavigationRailValue = WideNavigationRailValue.Collapsed
): WideNavigationRailState

Create and remember a WideNavigationRailState.

fun ripple(
    bounded: Boolean = true,
    radius: Dp = Dp.Unspecified,
    color: Color = Color.Unspecified
): IndicationNodeFactory

Creates a Ripple using the provided values and values inferred from the theme.

A Ripple is a Material implementation of Indication that expresses different Interactions by drawing ripple animations and state layers.

A Ripple responds to PressInteraction.Press by starting a new ripple animation, and responds to other Interactions by showing a fixed state layer with varying alpha values depending on the Interaction.

MaterialTheme provides Ripples using androidx.compose.foundation.LocalIndication, so a Ripple will be used as the default Indication inside components such as androidx.compose.foundation.clickable and androidx.compose.foundation.indication, in addition to Material provided components that use a Ripple as well.

You can also explicitly create a Ripple and provide it to custom components in order to change the parameters from the default, such as to create an unbounded ripple with a fixed size.

To create a Ripple with a manually defined color that can change over time, see the other ripple overload with a ColorProducer parameter. This will avoid unnecessary recompositions when changing the color, and preserve existing ripple state when the color changes.

Parameters
bounded: Boolean = true

If true, ripples are clipped by the bounds of the target layout. Unbounded ripples always animate from the target layout center, bounded ripples animate from the touch position.

radius: Dp = Dp.Unspecified

the radius for the ripple. If Dp.Unspecified is provided then the size will be calculated based on the target layout size.

color: Color = Color.Unspecified

the color of the ripple. This color is usually the same color used by the text or iconography in the component. This color will then have RippleDefaults.RippleAlpha applied to calculate the final color used to draw the ripple. If Color.Unspecified is provided the color used will be LocalContentColor instead.

fun ripple(
    color: ColorProducer,
    bounded: Boolean = true,
    radius: Dp = Dp.Unspecified
): IndicationNodeFactory

Creates a Ripple using the provided values and values inferred from the theme.

A Ripple is a Material implementation of Indication that expresses different Interactions by drawing ripple animations and state layers.

A Ripple responds to PressInteraction.Press by starting a new ripple animation, and responds to other Interactions by showing a fixed state layer with varying alpha values depending on the Interaction.

MaterialTheme provides Ripples using androidx.compose.foundation.LocalIndication, so a Ripple will be used as the default Indication inside components such as androidx.compose.foundation.clickable and androidx.compose.foundation.indication, in addition to Material provided components that use a Ripple as well.

You can also explicitly create a Ripple and provide it to custom components in order to change the parameters from the default, such as to create an unbounded ripple with a fixed size.

To create a Ripple with a static color, see the ripple overload with a Color parameter. This overload is optimized for Ripples that have dynamic colors that change over time, to reduce unnecessary recompositions.

Parameters
color: ColorProducer

the color of the ripple. This color is usually the same color used by the text or iconography in the component. This color will then have RippleDefaults.RippleAlpha applied to calculate the final color used to draw the ripple. If you are creating this ColorProducer outside of composition (where it will be automatically remembered), make sure that its instance is stable (such as by remembering the object that holds it), or remember the returned ripple object to make sure that ripple nodes are not being created each recomposition.

bounded: Boolean = true

If true, ripples are clipped by the bounds of the target layout. Unbounded ripples always animate from the target layout center, bounded ripples animate from the touch position.

radius: Dp = Dp.Unspecified

the radius for the ripple. If Dp.Unspecified is provided then the size will be calculated based on the target layout size.

Extension functions

FloatingActionButtonMenuItem

@ExperimentalMaterial3ExpressiveApi
@Composable
fun FloatingActionButtonMenuScope.FloatingActionButtonMenuItem(
    onClick: () -> Unit,
    text: @Composable () -> Unit,
    icon: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    containerColor: Color = MaterialTheme.colorScheme.primaryContainer,
    contentColor: Color = contentColorFor(containerColor)
): Unit

FAB Menu Items should be used within a FloatingActionButtonMenu to provide additional choices to the user after clicking a FAB.

import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Label
import androidx.compose.material.icons.automirrored.filled.Message
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Archive
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Contacts
import androidx.compose.material.icons.filled.People
import androidx.compose.material.icons.filled.Snooze
import androidx.compose.material3.FloatingActionButtonMenu
import androidx.compose.material3.FloatingActionButtonMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.material3.ToggleFloatingActionButton
import androidx.compose.material3.ToggleFloatingActionButtonDefaults.animateIcon
import androidx.compose.material3.animateFloatingActionButton
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.semantics.CustomAccessibilityAction
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.customActions
import androidx.compose.ui.semantics.isTraversalGroup
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.stateDescription
import androidx.compose.ui.semantics.traversalIndex
import androidx.compose.ui.unit.dp

val listState = rememberLazyListState()
val fabVisible by remember { derivedStateOf { listState.firstVisibleItemIndex == 0 } }

Box {
    LazyColumn(state = listState, modifier = Modifier.fillMaxSize()) {
        for (index in 0 until 100) {
            item { Text(text = "List item - $index", modifier = Modifier.padding(24.dp)) }
        }
    }

    val items =
        listOf(
            Icons.AutoMirrored.Filled.Message to "Reply",
            Icons.Filled.People to "Reply all",
            Icons.Filled.Contacts to "Forward",
            Icons.Filled.Snooze to "Snooze",
            Icons.Filled.Archive to "Archive",
            Icons.AutoMirrored.Filled.Label to "Label",
        )

    var fabMenuExpanded by rememberSaveable { mutableStateOf(false) }

    BackHandler(fabMenuExpanded) { fabMenuExpanded = false }

    FloatingActionButtonMenu(
        modifier = Modifier.align(Alignment.BottomEnd),
        expanded = fabMenuExpanded,
        button = {
            ToggleFloatingActionButton(
                modifier =
                    Modifier.semantics {
                            traversalIndex = -1f
                            stateDescription = if (fabMenuExpanded) "Expanded" else "Collapsed"
                            contentDescription = "Toggle menu"
                        }
                        .animateFloatingActionButton(
                            visible = fabVisible || fabMenuExpanded,
                            alignment = Alignment.BottomEnd
                        ),
                checked = fabMenuExpanded,
                onCheckedChange = { fabMenuExpanded = !fabMenuExpanded }
            ) {
                val imageVector by remember {
                    derivedStateOf {
                        if (checkedProgress > 0.5f) Icons.Filled.Close else Icons.Filled.Add
                    }
                }
                Icon(
                    painter = rememberVectorPainter(imageVector),
                    contentDescription = null,
                    modifier = Modifier.animateIcon({ checkedProgress })
                )
            }
        }
    ) {
        items.forEachIndexed { i, item ->
            FloatingActionButtonMenuItem(
                modifier =
                    Modifier.semantics {
                        isTraversalGroup = true
                        // Add a custom a11y action to allow closing the menu when focusing
                        // the last menu item, since the close button comes before the first
                        // menu item in the traversal order.
                        if (i == items.size - 1) {
                            customActions =
                                listOf(
                                    CustomAccessibilityAction(
                                        label = "Close menu",
                                        action = {
                                            fabMenuExpanded = false
                                            true
                                        }
                                    )
                                )
                        }
                    },
                onClick = { fabMenuExpanded = false },
                icon = { Icon(item.first, contentDescription = null) },
                text = { Text(text = item.second) },
            )
        }
    }
}
Parameters
onClick: () -> Unit

called when this FAB Menu Item is clicked

text: @Composable () -> Unit

label displayed inside this FAB Menu Item

icon: @Composable () -> Unit

optional icon for this FAB Menu Item, typically an Icon

modifier: Modifier = Modifier

the Modifier to be applied to this FAB Menu Item

containerColor: Color = MaterialTheme.colorScheme.primaryContainer

the color used for the background of this FAB Menu Item

contentColor: Color = contentColorFor(containerColor)

the preferred color for content inside this FAB Menu Item. Defaults to either the matching content color for containerColor, or to the current LocalContentColor if containerColor is not a color from the theme.

NavigationBarItem

@Composable
fun RowScope.NavigationBarItem(
    selected: Boolean,
    onClick: () -> Unit,
    icon: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    label: (@Composable () -> Unit)? = null,
    alwaysShowLabel: Boolean = true,
    colors: NavigationBarItemColors = NavigationBarItemDefaults.colors(),
    interactionSource: MutableInteractionSource? = null
): Unit

Material Design navigation bar item.

Navigation bars offer a persistent and convenient way to switch between primary destinations in an app.

The recommended configuration for a NavigationBarItem depends on how many items there are inside a NavigationBar:

  • Three destinations: Display icons and text labels for all destinations.

  • Four destinations: Active destinations display an icon and text label. Inactive destinations display icons, and text labels are recommended.

  • Five destinations: Active destinations display an icon and text label. Inactive destinations use icons, and use text labels if space permits.

A NavigationBarItem always shows text labels (if it exists) when selected. Showing text labels if not selected is controlled by alwaysShowLabel.

Parameters
selected: Boolean

whether this item is selected

onClick: () -> Unit

called when this item is clicked

icon: @Composable () -> Unit

icon for this item, typically an Icon

modifier: Modifier = Modifier

the Modifier to be applied to this item

enabled: Boolean = true

controls the enabled state of this item. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

label: (@Composable () -> Unit)? = null

optional text label for this item

alwaysShowLabel: Boolean = true

whether to always show the label for this item. If false, the label will only be shown when this item is selected.

colors: NavigationBarItemColors = NavigationBarItemDefaults.colors()

NavigationBarItemColors that will be used to resolve the colors used for this item in different states. See NavigationBarItemDefaults.colors.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this item. You can use this to change the item's appearance or preview the item in different states. Note that if null is provided, interactions will still happen internally.

PlainTooltip

@Composable
@ExperimentalMaterial3Api
fun TooltipScope.PlainTooltip(
    modifier: Modifier = Modifier,
    caretSize: DpSize = DpSize.Unspecified,
    maxWidth: Dp = TooltipDefaults.plainTooltipMaxWidth,
    shape: Shape = TooltipDefaults.plainTooltipContainerShape,
    contentColor: Color = TooltipDefaults.plainTooltipContentColor,
    containerColor: Color = TooltipDefaults.plainTooltipContainerColor,
    tonalElevation: Dp = 0.dp,
    shadowElevation: Dp = 0.dp,
    content: @Composable () -> Unit
): Unit

Plain tooltip that provides a descriptive message.

Usually used with TooltipBox.

Parameters
modifier: Modifier = Modifier

the Modifier to be applied to the tooltip.

caretSize: DpSize = DpSize.Unspecified

DpSize for the caret of the tooltip, if a default caret is desired with a specific dimension. Please see TooltipDefaults.caretSize to see the default dimensions. Pass in Dp.Unspecified for this parameter if no caret is desired.

maxWidth: Dp = TooltipDefaults.plainTooltipMaxWidth

the maximum width for the plain tooltip

shape: Shape = TooltipDefaults.plainTooltipContainerShape

the Shape that should be applied to the tooltip container.

contentColor: Color = TooltipDefaults.plainTooltipContentColor

Color that will be applied to the tooltip's content.

containerColor: Color = TooltipDefaults.plainTooltipContainerColor

Color that will be applied to the tooltip's container.

tonalElevation: Dp = 0.dp

the tonal elevation of the tooltip.

shadowElevation: Dp = 0.dp

the shadow elevation of the tooltip.

content: @Composable () -> Unit

the composable that will be used to populate the tooltip's content.

RichTooltip

@Composable
@ExperimentalMaterial3Api
fun TooltipScope.RichTooltip(
    modifier: Modifier = Modifier,
    title: (@Composable () -> Unit)? = null,
    action: (@Composable () -> Unit)? = null,
    caretSize: DpSize = DpSize.Unspecified,
    maxWidth: Dp = TooltipDefaults.richTooltipMaxWidth,
    shape: Shape = TooltipDefaults.richTooltipContainerShape,
    colors: RichTooltipColors = TooltipDefaults.richTooltipColors(),
    tonalElevation: Dp = ElevationTokens.Level0,
    shadowElevation: Dp = RichTooltipTokens.ContainerElevation,
    text: @Composable () -> Unit
): Unit

Rich text tooltip that allows the user to pass in a title, text, and action. Tooltips are used to provide a descriptive message.

Usually used with TooltipBox

Parameters
modifier: Modifier = Modifier

the Modifier to be applied to the tooltip.

title: (@Composable () -> Unit)? = null

An optional title for the tooltip.

action: (@Composable () -> Unit)? = null

An optional action for the tooltip.

caretSize: DpSize = DpSize.Unspecified

DpSize for the caret of the tooltip, if a default caret is desired with a specific dimension. Please see TooltipDefaults.caretSize to see the default dimensions. Pass in Dp.Unspecified for this parameter if no caret is desired.

maxWidth: Dp = TooltipDefaults.richTooltipMaxWidth

the maximum width for the rich tooltip

shape: Shape = TooltipDefaults.richTooltipContainerShape

the Shape that should be applied to the tooltip container.

colors: RichTooltipColors = TooltipDefaults.richTooltipColors()

RichTooltipColors that will be applied to the tooltip's container and content.

tonalElevation: Dp = ElevationTokens.Level0

the tonal elevation of the tooltip.

shadowElevation: Dp = RichTooltipTokens.ContainerElevation

the shadow elevation of the tooltip.

text: @Composable () -> Unit

the composable that will be used to populate the rich tooltip's text.

SegmentedButton

@Composable
fun MultiChoiceSegmentedButtonRowScope.SegmentedButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    shape: Shape,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: SegmentedButtonColors = SegmentedButtonDefaults.colors(),
    border: BorderStroke = SegmentedButtonDefaults.borderStroke(colors.borderColor(enabled, checked)),
    contentPadding: PaddingValues = SegmentedButtonDefaults.ContentPadding,
    interactionSource: MutableInteractionSource? = null,
    icon: @Composable () -> Unit = { SegmentedButtonDefaults.Icon(checked) },
    label: @Composable () -> Unit
): Unit

Material Segmented Button. Segmented buttons help people select options, switch views, or sort elements.

A default Toggleable Segmented Button. Also known as Outlined Segmented Button. See Modifier.toggleable.

Toggleable segmented buttons should be used for cases where the selection is not mutually exclusive.

This should typically be used inside of a MultiChoiceSegmentedButtonRow

For a sample showing Segmented button with only checked icons see:

import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.TrendingUp
import androidx.compose.material.icons.filled.BookmarkBorder
import androidx.compose.material.icons.filled.StarBorder
import androidx.compose.material3.Icon
import androidx.compose.material3.MultiChoiceSegmentedButtonRow
import androidx.compose.material3.SegmentedButton
import androidx.compose.material3.SegmentedButtonDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier

val checkedList = remember { mutableStateListOf<Int>() }
val options = listOf("Favorites", "Trending", "Saved")
val icons =
    listOf(
        Icons.Filled.StarBorder,
        Icons.AutoMirrored.Filled.TrendingUp,
        Icons.Filled.BookmarkBorder
    )
MultiChoiceSegmentedButtonRow {
    options.forEachIndexed { index, label ->
        SegmentedButton(
            shape = SegmentedButtonDefaults.itemShape(index = index, count = options.size),
            icon = {
                SegmentedButtonDefaults.Icon(active = index in checkedList) {
                    Icon(
                        imageVector = icons[index],
                        contentDescription = null,
                        modifier = Modifier.size(SegmentedButtonDefaults.IconSize)
                    )
                }
            },
            onCheckedChange = {
                if (index in checkedList) {
                    checkedList.remove(index)
                } else {
                    checkedList.add(index)
                }
            },
            checked = index in checkedList
        ) {
            Text(label)
        }
    }
}
Parameters
checked: Boolean

whether this button is checked or not

onCheckedChange: (Boolean) -> Unit

callback to be invoked when the button is clicked. therefore the change of checked state in requested.

shape: Shape

the shape for this button

modifier: Modifier = Modifier

the Modifier to be applied to this button

enabled: Boolean = true

controls the enabled state of this button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

colors: SegmentedButtonColors = SegmentedButtonDefaults.colors()

SegmentedButtonColors that will be used to resolve the colors used for this

border: BorderStroke = SegmentedButtonDefaults.borderStroke(colors.borderColor(enabled, checked))

the border for this button, see SegmentedButtonColors Button in different states

contentPadding: PaddingValues = SegmentedButtonDefaults.ContentPadding

the spacing values to apply internally between the container and the * content

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this button. You can use this to change the button's appearance or preview the button in different states. Note that if null is provided, interactions will still happen internally.

icon: @Composable () -> Unit = { SegmentedButtonDefaults.Icon(checked) }

the icon slot for this button, you can pass null in unchecked, in which case the content will displace to show the checked icon, or pass different icon lambdas for unchecked and checked in which case the icons will crossfade.

label: @Composable () -> Unit

content to be rendered inside this button

SegmentedButton

@Composable
fun SingleChoiceSegmentedButtonRowScope.SegmentedButton(
    selected: Boolean,
    onClick: () -> Unit,
    shape: Shape,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: SegmentedButtonColors = SegmentedButtonDefaults.colors(),
    border: BorderStroke = SegmentedButtonDefaults.borderStroke(colors.borderColor(enabled, selected)),
    contentPadding: PaddingValues = SegmentedButtonDefaults.ContentPadding,
    interactionSource: MutableInteractionSource? = null,
    icon: @Composable () -> Unit = { SegmentedButtonDefaults.Icon(selected) },
    label: @Composable () -> Unit
): Unit

Material Segmented Button. Segmented buttons help people select options, switch views, or sort elements.

A default Toggleable Segmented Button. Also known as Outlined Segmented Button. See Modifier.selectable.

Selectable segmented buttons should be used for cases where the selection is mutually exclusive, when only one button can be selected at a time.

This should typically be used inside of a SingleChoiceSegmentedButtonRow

For a sample showing Segmented button with only checked icons see:

import androidx.compose.foundation.layout.size
import androidx.compose.material3.SegmentedButton
import androidx.compose.material3.SegmentedButtonDefaults
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var selectedIndex by remember { mutableStateOf(0) }
val options = listOf("Day", "Month", "Week")
SingleChoiceSegmentedButtonRow {
    options.forEachIndexed { index, label ->
        SegmentedButton(
            shape = SegmentedButtonDefaults.itemShape(index = index, count = options.size),
            onClick = { selectedIndex = index },
            selected = index == selectedIndex
        ) {
            Text(label)
        }
    }
}
Parameters
selected: Boolean

whether this button is selected or not

onClick: () -> Unit

callback to be invoked when the button is clicked. therefore the change of checked state in requested.

shape: Shape

the shape for this button

modifier: Modifier = Modifier

the Modifier to be applied to this button

enabled: Boolean = true

controls the enabled state of this button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.

colors: SegmentedButtonColors = SegmentedButtonDefaults.colors()

SegmentedButtonColors that will be used to resolve the colors used for this

border: BorderStroke = SegmentedButtonDefaults.borderStroke(colors.borderColor(enabled, selected))

the border for this button, see SegmentedButtonColors Button in different states

contentPadding: PaddingValues = SegmentedButtonDefaults.ContentPadding

the spacing values to apply internally between the container and the content

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this button. You can use this to change the button's appearance or preview the button in different states. Note that if null is provided, interactions will still happen internally.

icon: @Composable () -> Unit = { SegmentedButtonDefaults.Icon(selected) }

the icon slot for this button, you can pass null in unchecked, in which case the content will displace to show the checked icon, or pass different icon lambdas for unchecked and checked in which case the icons will crossfade.

label: @Composable () -> Unit

content to be rendered inside this button

animateFloatingActionButton

@ExperimentalMaterial3ExpressiveApi
fun Modifier.animateFloatingActionButton(
    visible: Boolean,
    alignment: Alignment,
    targetScale: Float = FloatingActionButtonDefaults.ShowHideTargetScale,
    scaleAnimationSpec: AnimationSpec<Float>? = null,
    alphaAnimationSpec: AnimationSpec<Float>? = null
): Modifier

Apply this modifier to a FloatingActionButton to show or hide it with an animation, typically based on the app's main content scrolling.

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FabPosition
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MediumFloatingActionButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.animateFloatingActionButton
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val listState = rememberLazyListState()
// The FAB is initially shown. Upon scrolling past the first item we hide the FAB by using a
// remembered derived state to minimize unnecessary compositions.
val fabVisible by remember { derivedStateOf { listState.firstVisibleItemIndex == 0 } }

Scaffold(
    floatingActionButton = {
        MediumFloatingActionButton(
            modifier =
                Modifier.animateFloatingActionButton(
                    visible = fabVisible,
                    alignment = Alignment.BottomEnd
                ),
            onClick = { /* do something */ },
        ) {
            Icon(
                Icons.Filled.Add,
                contentDescription = "Localized description",
                modifier = Modifier.size(FloatingActionButtonDefaults.MediumIconSize),
            )
        }
    },
    floatingActionButtonPosition = FabPosition.End,
) {
    LazyColumn(state = listState, modifier = Modifier.fillMaxSize()) {
        for (index in 0 until 100) {
            item { Text(text = "List item - $index", modifier = Modifier.padding(24.dp)) }
        }
    }
}
Parameters
visible: Boolean

whether the FAB should be shown or hidden with an animation

alignment: Alignment

the direction towards which the FAB should be scaled to and from

targetScale: Float = FloatingActionButtonDefaults.ShowHideTargetScale

the initial scale value when showing the FAB and the final scale value when hiding the FAB

scaleAnimationSpec: AnimationSpec<Float>? = null

the AnimationSpec to use for the scale part of the animation, if null the Fast Spatial spring spec from the MotionScheme will be used

alphaAnimationSpec: AnimationSpec<Float>? = null

the AnimationSpec to use for the alpha part of the animation, if null the Fast Effects spring spec from the MotionScheme will be used

contentColorFor

fun ColorScheme.contentColorFor(backgroundColor: Color): Color

The Material color system contains pairs of colors that are typically used for the background and content color inside a component. For example, a Button typically uses primary for its background, and onPrimary for the color of its content (usually text or iconography).

This function tries to match the provided backgroundColor to a 'background' color in this ColorScheme, and then will return the corresponding color used for content. For example, when backgroundColor is ColorScheme.primary, this will return ColorScheme.onPrimary.

If backgroundColor does not match a background color in the theme, this will return Color.Unspecified.

Returns
Color

the matching content color for backgroundColor. If backgroundColor is not present in the theme's ColorScheme, then returns Color.Unspecified.

See also
contentColorFor

minimumInteractiveComponentSize

fun Modifier.minimumInteractiveComponentSize(): Modifier

Reserves at least 48.dp in size to disambiguate touch interactions if the element would measure smaller.

https://m3.material.io/foundations/designing/structure#dab862b1-e042-4c40-b680-b484b9f077f6

This uses the Material recommended minimum size of 48.dp x 48.dp, which may not the same as the system enforced minimum size. The minimum clickable / touch target size (48.dp by default) is controlled by the system via ViewConfiguration and automatically expanded at the touch input layer.

This modifier is not needed for touch target expansion to happen. It only affects layout, to make sure there is adequate space for touch target expansion.

Because layout constraints are affected by modifier order, for this modifier to take effect, it must come before any size modifiers on the element that might limit its constraints.

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.size
import androidx.compose.material3.minimumInteractiveComponentSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

@Composable
fun Widget(color: Color, modifier: Modifier = Modifier) {
    // Default size is 24.dp, which is smaller than the recommended touch target
    Box(modifier.size(24.dp).background(color))
}

Column(Modifier.border(1.dp, Color.Black)) {
    // Not interactable, no need for touch target enforcement
    Widget(Color.Red)

    Widget(
        color = Color.Green,
        modifier =
            Modifier.clickable { /* do something */ }
                // Component is now interactable, so it should enforce a sufficient touch target
                .minimumInteractiveComponentSize()
    )

    Widget(
        color = Color.Blue,
        modifier =
            Modifier.clickable { /* do something */ }
                // Component is now interactable, so it should enforce a sufficient touch target
                .minimumInteractiveComponentSize()
                // Any size modifiers should come after `minimumInteractiveComponentSize`
                // so as not to interfere with layout expansion
                .size(36.dp)
    )
}
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.selection.toggleable
import androidx.compose.material3.Checkbox
import androidx.compose.material3.Text
import androidx.compose.material3.minimumInteractiveComponentSize
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.dp

var checked by remember { mutableStateOf(false) }

// The entire row accepts interactions to toggle the checkbox,
// so we apply `minimumInteractiveComponentSize`
Row(
    verticalAlignment = Alignment.CenterVertically,
    modifier =
        Modifier.toggleable(
                value = checked,
                onValueChange = { checked = it },
                role = Role.Checkbox,
            )
            .minimumInteractiveComponentSize()
) {
    // Cannot rely on Checkbox for touch target expansion because it only enforces
    // `minimumInteractiveComponentSize` if onCheckedChange is non-null
    Checkbox(checked = checked, onCheckedChange = null)
    Spacer(Modifier.width(8.dp))
    Text("Label for checkbox")
}

surfaceColorAtElevation

fun ColorScheme.surfaceColorAtElevation(elevation: Dp): Color

Computes the surface tonal color at different elevation levels e.g. surface1 through surface5.

Parameters
elevation: Dp

Elevation value used to compute alpha of the color overlay layer.

Returns
Color

the ColorScheme.surface color with an alpha of the ColorScheme.surfaceTint color overlaid on top of it.

@ExperimentalMaterial3ExpressiveApi
@Composable
fun RoundedPolygon.toPath(startAngle: Int = 0): Path

Returns a Path that is remembered across compositions for this RoundedPolygon.

Parameters
startAngle: Int = 0

the angle (in degrees) from which to begin drawing the generated path. By default, it is set to 0 degrees, meaning the Path begins drawing at the 3 o'clock position. The returned path is rotated by this angle around the RoundedPolygon's centroid (centerX, centerY).

@ExperimentalMaterial3ExpressiveApi
fun Morph.toPath(progress: Float, path: Path = Path(), startAngle: Int = 0): Path

Returns a Path for this Morph.

Parameters
progress: Float

the Morph's progress

path: Path = Path()

a Path to rewind and set with the new path data. In case provided, this Path would be the returned one.

startAngle: Int = 0

the angle (in degrees) from which to begin drawing the generated path. By default, it is set to 0 degrees, meaning the Path begins drawing at the 3 o'clock position.

@ExperimentalMaterial3ExpressiveApi
@Composable
fun RoundedPolygon.toShape(startAngle: Int = 0): Shape

Returns a Shape that is remembered across compositions for this RoundedPolygon.

Parameters
startAngle: Int = 0

the angle (in degrees) from which to begin drawing the generated shape's path. By default, it is set to 0 degrees, meaning the shape's path begins drawing at the 3 o'clock position. The returned path is rotated by this angle around the RoundedPolygon's centroid (centerX, centerY).

Top-level properties

LocalAbsoluteTonalElevation

val LocalAbsoluteTonalElevationProvidableCompositionLocal<Dp>

CompositionLocal containing the current absolute elevation provided by Surface components. This absolute elevation is a sum of all the previous elevations. Absolute elevation is only used for calculating surface tonal colors, and is not used for drawing the shadow in a Surface.

LocalContentColor

val LocalContentColorProvidableCompositionLocal<Color>

CompositionLocal containing the preferred content color for a given position in the hierarchy. This typically represents the on color for a color in ColorScheme. For example, if the background color is ColorScheme.surface, this color is typically set to ColorScheme.onSurface.

This color should be used for any typography / iconography, to ensure that the color of these adjusts when the background color changes. For example, on a dark background, text should be light, and on a light background, text should be dark.

Defaults to Color.Black if no color has been explicitly set.

LocalMinimumInteractiveComponentEnforcement

@ExperimentalMaterial3Api
val LocalMinimumInteractiveComponentEnforcementProvidableCompositionLocal<Boolean>

CompositionLocal that configures whether Material components that have a visual size that is lower than the minimum touch target size for accessibility (such as Button) will include extra space outside the component to ensure that they are accessible. If set to false there will be no extra space, and so it is possible that if the component is placed near the edge of a layout / near to another component without any padding, there will not be enough space for an accessible touch target.

LocalMinimumInteractiveComponentSize

val LocalMinimumInteractiveComponentSizeProvidableCompositionLocal<Dp>

CompositionLocal that configures the minimum touch target size for Material components (such as Button) to ensure they are accessible. If a component has a visual size that is lower than the minimum touch target size, extra space outside the component will be included. If set to 0.dp, there will be no extra space, and so it is possible that if the component is placed near the edge of a layout / near to another component without any padding, there will not be enough space for an accessible touch target.

LocalRippleConfiguration

val LocalRippleConfigurationProvidableCompositionLocal<RippleConfiguration?>

CompositionLocal used for providing RippleConfiguration down the tree. This acts as a tree-local 'override' for ripples used inside components that you cannot directly control, such as to change the color of a specific component's ripple, or disable it entirely by providing null.

In most cases you should rely on the default theme behavior for consistency with other components

  • this exists as an escape hatch for individual components and is not intended to be used for full theme customization across an application. For this use case you should instead build your own custom ripple that queries your design system theme values directly using createRippleModifierNode.

LocalTextStyle

val LocalTextStyleProvidableCompositionLocal<TextStyle>

CompositionLocal containing the preferred TextStyle that will be used by Text components by default. To set the value for this CompositionLocal, see ProvideTextStyle which will merge any missing TextStyle properties with the existing TextStyle set in this CompositionLocal.

See also
ProvideTextStyle

LocalTonalElevationEnabled

val LocalTonalElevationEnabledProvidableCompositionLocal<Boolean>

Composition Local used to check if ColorScheme.applyTonalElevation will be applied down the tree.

Setting this value to false will cause all subsequent surfaces down the tree to not apply tonalElevation.

Extension properties

val TimePickerState.isPmBoolean

Indicates whether the selected time falls within the period from 12 PM inclusive to 12 AM non inclusive.