Skip to content

OverlayListPopup

OverlayListPopup is a popup list component in COUI used to display a popup menu with multiple options. It provides a lightweight, floating temporary list suitable for various dropdown menus, context menus, and similar scenarios.

Prerequisite

This component depends on Scaffold providing COUIPopupHost to render popup content. It must be used within Scaffold, otherwise popup content will not render correctly.

Import

kotlin
import io.github.suqi8.coui.kmp.overlay.OverlayListPopup
import io.github.suqi8.coui.kmp.basic.ListPopupColumn
import io.github.suqi8.coui.kmp.basic.ListPopupDefaults
import io.github.suqi8.coui.kmp.basic.DropdownImpl
import io.github.suqi8.coui.kmp.basic.PopupPositionProvider

Basic Usage

The OverlayListPopup component can be used to create simple dropdown menus:

kotlin
var showPopup by remember { mutableStateOf(false) }
var selectedIndex by remember { mutableStateOf(0) }
val items = listOf("Option 1", "Option 2", "Option 3")

Scaffold {
    Box {
        TextButton(
            text = "Click to show menu",
            onClick = { showPopup = true }
        )
        OverlayListPopup(
            show = showPopup,
            alignment = PopupPositionProvider.Align.Start,
            onDismissRequest = { showPopup = false } // Close the popup menu
        ) {
            ListPopupColumn {
                items.forEachIndexed { index, string ->
                    DropdownImpl(
                        text = string,
                        optionSize = items.size,
                        isSelected = selectedIndex == index,
                        index = index,
                        onSelectedIndexChange = {
                            selectedIndex = index
                            showPopup = false // Close the popup menu
                        }
                    )
                }
            }
        }
    }
}

Component States

Different Alignments

OverlayListPopup can be set with different alignment options:

kotlin
var showPopup by remember { mutableStateOf(false) }

OverlayListPopup(
    show = showPopup,
    onDismissRequest = { showPopup = false }, // Close the popup menu
    alignment = PopupPositionProvider.Align.Start
) {
    ListPopupColumn {
        // Custom content
    }
}

Disable Window Dimming

kotlin
var showPopup by remember { mutableStateOf(false) }

OverlayListPopup(
    show = showPopup,
    onDismissRequest = { showPopup = false }, // Close the popup menu
    enableWindowDim = false // Disable dimming layer
) {
    ListPopupColumn {
        // Custom content
    }
}

Context Menu Positioning

Besides the default dropdown provider, ListPopupDefaults.ContextMenuPositionProvider anchors the popup to a corner of the anchor, combined with the corner alignments (TopStart / TopEnd / BottomStart / BottomEnd):

kotlin
var showPopup by remember { mutableStateOf(false) }

OverlayListPopup(
    show = showPopup,
    popupPositionProvider = ListPopupDefaults.ContextMenuPositionProvider,
    alignment = PopupPositionProvider.Align.TopEnd,
    onDismissRequest = { showPopup = false }
) {
    ListPopupColumn {
        // Custom content
    }
}

You can also build a dropdown provider with custom margins via ListPopupDefaults.dropdownPositionProvider(verticalMargin, horizontalMargin).

Properties

OverlayListPopup

Property NameTypeDescriptionDefault Value
showBooleanWhether to show the popup.-
popupModifierModifierModifier applied to the popup container.Modifier
popupPositionProviderPopupPositionProviderProvides position calculation logic for the popup.ListPopupDefaults.DropdownPositionProvider
alignmentPopupPositionProvider.AlignSpecifies the alignment of the popup relative to the anchor.PopupPositionProvider.Align.Start
enableWindowDimBooleanWhether to dim the background when popup is shown.true
onDismissRequest(() -> Unit)?Called when the user requests dismissal (e.g., clicking outside).null
onDismissFinished(() -> Unit)?Invoked after the hide animation completes; not invoked if the hide is cancelled mid-flight (e.g., show toggled back to true)null
maxHeightDp?Maximum height of the popup content.null
minWidthDpMinimum width of the popup content.ListPopupDefaults.MinWidth
renderInRootScaffoldBooleanWhether to render the popup in the root (outermost) Scaffold. When true, the popup covers the full screen. When false, it renders within the current Scaffold's bounds with position compensation.true
content@Composable () -> UnitThe content to display inside the popup.-

ListPopupColumn

Property NameTypeDescriptionDefault Value
content@Composable () -> UnitThe list content to display inside the column.-

DropdownImpl can be used as a standard row inside ListPopupColumn. Set enabled = false to disable a row; disabled rows are not clickable and use the disabled text color.

kotlin
DropdownImpl(
    text = "Disabled option",
    optionSize = items.size,
    isSelected = false,
    index = 1,
    enabled = false,
    onSelectedIndexChange = {}
)

The text-based overload:

Property NameTypeDescriptionDefault Value
textStringText shown for the option-
optionSizeIntTotal number of options-
isSelectedBooleanWhether this option is selected-
indexIntIndex of this option-
dropdownColorsDropdownColorsColor configuration for the optionDropdownDefaults.dropdownColors()
enabledBooleanWhether this option can be clickedtrue
dialogModeBooleanWhether the row is shown in dialog modefalse
onSelectedIndexChange(Int) -> UnitCallback when this option is clicked-

The item-based overload accepts a DropdownItem (with optional icon and summary) and exposes extra layout flags:

Property NameTypeDescriptionDefault Value
itemDropdownItemThe item of the current option-
optionSizeIntTotal number of options-
isSelectedBooleanWhether this option is selected-
indexIntIndex of this option-
dropdownColorsDropdownColorsColor configuration for the optionDropdownDefaults.dropdownColors()
enabledBooleanWhether this option can be clickeditem.enabled
dialogModeBooleanWhether the row is shown in dialog modefalse
hasSubmenuBooleanWhen true, the row acts as a submenu trigger: a trailing chevron is shown instead of the selection checkfalse
isFirstBooleanWhether this row is the first row of the entire popup (controls the larger top padding in popup mode)index == 0
isLastBooleanWhether this row is the last row of the entire popup (controls the larger bottom padding in popup mode)index == optionSize - 1
onSelectedIndexChange(Int) -> UnitCallback when this option is clicked-

PopupPositionProvider.Align

ValueDescription
StartAligns the popup to the start of the anchor.
EndAligns the popup to the end of the anchor.
TopStartAligns the popup to the top-start of the anchor.
TopEndAligns the popup to the top-end of the anchor.
BottomStartAligns the popup to the bottom-start of the anchor.
BottomEndAligns the popup to the bottom-end of the anchor.

ListPopupDefaults Object

The ListPopupDefaults object provides default values and position providers for the popup.

Constants

Constant NameTypeDescriptionValue
MinWidthDpDefault minimum width of the popup178.dp
MaxWidthDpMaximum width clamp used by ListPopupColumn232.dp
MinPopupHeightDpMinimum height the popup will occupy when measured50.dp

Position Providers

NameTypeDescription
DropdownPositionProviderPopupPositionProviderAnchors the popup below (or above when there is no room) the anchor, for dropdown-style menus
ContextMenuPositionProviderPopupPositionProviderAnchors the popup to a corner of the anchor, for context menus
dropdownPositionProvider(verticalMargin, horizontalMargin)PopupPositionProviderFactory creating a dropdown provider with custom margins (defaults: vertical 8.dp, horizontal 0.dp)

Changelog

Released under the Apache-2.0 License