Skip to content

Conversation

@faogustavo
Copy link
Collaborator

@faogustavo faogustavo commented Dec 24, 2025

  • Fixed index emission on SelectableLazyColumn when the selection changes by the speed search
  • Created 'EmptySpeedSearchMatcher' to easily identify when the filter text is empty
    • This matches is automatically returned in the SpeedSearchState.matcher when the text is empty
  • Added 'dismissOnLoseFocus' to SpeedSearchArea to keep the filter when the focus is left from the component
  • Added 'currentMatcher' to the 'SpeedSearchState', allowing the user use it for filtering purposes
  • Created convenience function on top of 'SpeedSearchMatcher' to check if the given text matches or not
  • Created convenience functions to support filtering collections based on the speed search matcher
  • Added a new page in the samples to test all SpeedSearch components and their variants
  • Added documentation for a bunch of public APIs that were missing

Evidences

Filter Speed Search
Screen Recording 2025-12-23 at 22 09 11

Release notes

⚠️ Important Changes

  • Added 'dismissOnLoseFocus' property to SpeedSearchArea, allowing users to choose if they want to keep the input visible on lose focus
    • This is important for cases that you want to use SpeedSearch as a filter

New features

  • Added support for filtering Collections using SpeedSearchMatcher.
    • Check the '.filter()' extension functions available in the 'org.jetbrains.jewel.foundation.search' package

Bug fixes

  • Fixed an issue that was not triggering the 'onSelectedIndexesChange' call when the selection gets changed by the SpeedSearch

Note

Introduces filtering-focused improvements and small fixes around speed search and selection.

  • SpeedSearchArea API: new overload accepting external SpeedSearchState, rememberSpeedSearchState, dismissOnLoseFocus flag, and SpeedSearchState.currentMatcher + visibility controls; internal batching/caching for better performance.
  • Matcher utilities: EmptySpeedSearchMatcher, SpeedSearchMatcher.doesMatch, and Iterable.filter(...) extensions (strings and generics).
  • Selection/scroll behavior: SpeedSearchableLazyColumnScrollEffect now reports selection via onSelectedIndexChange; SelectableLazyColumn emits indices when selection changes via SpeedSearch and syncs lastActiveItemIndex.
  • Samples/tests: new "Speed Search" showcase (tree, highlight, filter); added unit/UI tests for filtering and focus dismissal behavior; updated existing LazyColumn/Tree tests to cover dismissOnLoseFocus=false.

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

- Fixed index emission on SelectableLazyColumn when the selection changes by the speed search
- Created 'EmptySpeedSearchMatcher' to easily identify when the filter text is empty
  - This matches is automatically returned in the SpeedSearchState.matcher when the text is empty
- Added 'dismissOnLoseFocus' to SpeedSearchArea to keep the filter when the focus is left from the component
- Added 'currentMatcher' to the 'SpeedSearchState', allowing the user use it for filtering purposes
- Created convenience function on top of 'SpeedSearchMatcher' to check if the given text matches or not
- Created convenience functions to support filtering collections based on the speed search matcher
Copy link
Collaborator

@wellingtoncosta wellingtoncosta left a comment

Choose a reason for hiding this comment

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

Just small suggestions, LGTM overall.

public fun `filter strings should return only exact matching items`() {
val items = listOf("apple", "pineapple", "application", "banana")
val matcher = SpeedSearchMatcher.exactSubstringMatcher("apple")
val result = items.filter(matcher) { it }
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you can use the Iterable<String>.filter() overload here to avoid this { it } block.

public fun `filter strings should return empty list when no items match`() {
val items = listOf("apple", "banana", "cherry")
val matcher = SpeedSearchMatcher.exactSubstringMatcher("xyz")
val result = items.filter(matcher) { it }
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ditto

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.

2 participants