Skip to content

[JEWEL-1244] Fix ListComboBox External SelectedIndex Changes Not Syncing To Internal State#3418

Open
DanielSouzaBertoldi wants to merge 1 commit intoJetBrains:masterfrom
DanielSouzaBertoldi:dsb/JEWEL-1244
Open

[JEWEL-1244] Fix ListComboBox External SelectedIndex Changes Not Syncing To Internal State#3418
DanielSouzaBertoldi wants to merge 1 commit intoJetBrains:masterfrom
DanielSouzaBertoldi:dsb/JEWEL-1244

Conversation

@DanielSouzaBertoldi
Copy link
Collaborator

@DanielSouzaBertoldi DanielSouzaBertoldi commented Feb 10, 2026

Context

Currently, our Combo Box implementation only updates its selected index internally. This means that, if users want to programmatically change it, the change won't be respected by our Combo Box. If the user clicks on a ComboBox, it'll show the value of whatever the user chose previously as the current selected item, not the item that was set by the code.

Changes

  • Added selectedIndex to our LaunchedEffect in ComboBoxImpl, so that we can update the list state with the current selected index
  • Added unit tests

If you'd like to test this yourself, apply the git patch below:

Details

Index: platform/jewel/samples/showcase/src/main/kotlin/org/jetbrains/jewel/samples/showcase/components/ComboBoxes.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/platform/jewel/samples/showcase/src/main/kotlin/org/jetbrains/jewel/samples/showcase/components/ComboBoxes.kt b/platform/jewel/samples/showcase/src/main/kotlin/org/jetbrains/jewel/samples/showcase/components/ComboBoxes.kt
--- a/platform/jewel/samples/showcase/src/main/kotlin/org/jetbrains/jewel/samples/showcase/components/ComboBoxes.kt	(revision db891e692f6611bc85709ecbe66a8b0fe87d226b)
+++ b/platform/jewel/samples/showcase/src/main/kotlin/org/jetbrains/jewel/samples/showcase/components/ComboBoxes.kt	(date 1770752708307)
@@ -2,6 +2,7 @@
 // Apache 2.0 license.
 package org.jetbrains.jewel.samples.showcase.components
 
+import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.FlowRow
@@ -101,10 +102,8 @@
 private fun ListComboBoxes() {
     FlowRow(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
         Column(Modifier.weight(1f).widthIn(min = 125.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
-            Text("String-based API")
-            var selectedIndex by remember { mutableIntStateOf(2) }
-            val selectedItemText = if (selectedIndex >= 0) stringItems[selectedIndex] else "[none]"
-            InfoText(text = "Selected item: $selectedItemText")
+            var selectedIndex by remember { mutableIntStateOf(0) }
+            Text("Reset", modifier = Modifier.clickable(onClick = { selectedIndex = 0 }))
 
             ListComboBox(
                 items = stringItems,
@@ -203,8 +202,8 @@
 private fun EditableListComboBoxes() {
     FlowRow(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
         Column(Modifier.weight(1f).widthIn(min = 125.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
-            Text("String-based API, enabled")
-            var selectedIndex by remember { mutableIntStateOf(2) }
+            var selectedIndex by remember { mutableIntStateOf(0) }
+            Text("Reset", modifier = Modifier.clickable(onClick = { selectedIndex = 0 }))
             val selectedItemText = if (selectedIndex >= 0) stringItems[selectedIndex] else "[none]"
             InfoText(text = "Selected item: $selectedItemText")
 

Evidences

Before After
ListComboBox
Screen.Recording.2026-02-10.at.16.47.24.mov
Screen.Recording.2026-02-10.at.16.43.26.mov
EditableComboBox
Screen.Recording.2026-02-10.at.16.47.54.mov
Screen.Recording.2026-02-10.at.16.43.54.mov

Note

Medium Risk
Changes selection synchronization and popup-visible behavior in core UI components, which could subtly affect keyboard/mouse selection and commit-on-close flows, but is covered by new UI tests.

Overview
Ensures ListComboBox and EditableListComboBox correctly reflect programmatic (selectedIndex) changes by syncing selectedIndex into the internal SelectableLazyListState only when the popup is closed, avoiding selection jumps while users are navigating an open popup.

Adds regression UI tests covering external selectedIndex resets for both combo box variants, validating correct selection highlighting and non-disruption while the popup is visible.

Written by Cursor Bugbot for commit 8f5a58d. This will update automatically on new commits. Configure here.

}

LaunchedEffect(itemKeys, selectedIndex, popupManager.isPopupVisible.value) {
if (!popupManager.isPopupVisible.value) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We really don't want to mess with the popup while its visible and the user is actively using it. This prevents any changes made programmatically from happening during this state.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants