{"id":24961708,"url":"https://github.com/mejdi14/kmp-searchable-dropdown","last_synced_at":"2025-10-27T10:01:46.096Z","repository":{"id":272353794,"uuid":"916172608","full_name":"mejdi14/KMP-Searchable-Dropdown","owner":"mejdi14","description":"Dropdown for Compose Multiplatform with search option and multi-selection","archived":false,"fork":false,"pushed_at":"2025-03-04T10:31:57.000Z","size":20252,"stargazers_count":16,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-24T19:07:46.877Z","etag":null,"topics":["android","android-application","animation","dropdown","dropdownmenu","jetpack-compose","menu","menubar","multiselect","multiselect-drodpdown","searchable","ui"],"latest_commit_sha":null,"homepage":"https://mejdi14.github.io/KMP-Searchable-Dropdown/","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mejdi14.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-13T15:38:57.000Z","updated_at":"2025-03-18T09:48:10.000Z","dependencies_parsed_at":"2025-01-13T22:25:37.209Z","dependency_job_id":"b5934243-1165-4ec9-8eb5-cf6e7bf58d16","html_url":"https://github.com/mejdi14/KMP-Searchable-Dropdown","commit_stats":null,"previous_names":["mejdi14/kmp-searchable-dropdown"],"tags_count":40,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mejdi14%2FKMP-Searchable-Dropdown","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mejdi14%2FKMP-Searchable-Dropdown/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mejdi14%2FKMP-Searchable-Dropdown/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mejdi14%2FKMP-Searchable-Dropdown/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mejdi14","download_url":"https://codeload.github.com/mejdi14/KMP-Searchable-Dropdown/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248304940,"owners_count":21081551,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","android-application","animation","dropdown","dropdownmenu","jetpack-compose","menu","menubar","multiselect","multiselect-drodpdown","searchable","ui"],"created_at":"2025-02-03T08:56:10.249Z","updated_at":"2025-10-27T10:01:45.981Z","avatar_url":"https://github.com/mejdi14.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eWelcome to KMP Searchable Dropdown 👋\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://developer.android.com/guide/topics/manifest/uses-sdk-element\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/API-15%2B-blue.svg?style=flat\" alt=\"Minimum API Level\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://maven-badges.herokuapp.com/maven-central/com.example/your-library\"\u003e\n    \u003cimg src=\"https://maven-badges.herokuapp.com/maven-central/com.example/your-library/badge.svg\" alt=\"Maven Central\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://opensource.org/licenses/MIT\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/License-MIT-yellow.svg\" alt=\"License: MIT\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://android-arsenal.com/\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Android%20Arsenal-Searchable%20Dropdown-green.svg?style=flat\" alt=\"Android Arsenal\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\n## ✨ Demo\n\n\u003cdiv style=\"display: flex; justify-content: center; align-items: center;\"\u003e\n  \u003cimg \n    src=\"https://raw.githubusercontent.com/mejdi14/KMP-Searchable-Dropdown/main/demo/banner.webp\"\n    height=\"500\"\n    width=\"645\"\n    style=\"margin-right: 20px;\"\n  /\u003e\n\n\u003c/div\u003e\n\n\n\n## Installation\n\nAdd this to your module's `build.gradle` file (make sure the version matches the JitPack badge\nabove):\n\n```gradle\ndependencies {\n\t...\n\timplementation(\"io.github.mejdi14:KMP-Searchable-Dropdown:1.1.0\")\n}\n```\n\n## :fire:How to use\n\n``` kotlin\n/* use your own list of objects\nhere I used this Data Class as an example:\ndata class People(\n    val name: String,\n    val photo: DrawableResource,\n    val job: String\n)\n*/\nval people = listOf(\n    People(\"Arij\", Res.drawable.student2, \"Software engineer\"),\n    People(\"Mejdi\", Res.drawable.student1, \"Software engineer\"),\n    People(\"Sami\", Res.drawable.student3, \"Designer\"),\n    )\n    SearchableDropdown(\n        items = people,\n        searchSettings = SearchSettings(\n            searchProperties = listOf(\n                People::name,\n                People::job,\n            )\n        ),\n        dropdownConfig = DropdownConfig(shape = RoundedCornerShape(8.dp)),\n        itemContentConfig = ItemContentConfig.Default(DefaultDropdownItem\u003cStudent\u003e(title = Student::name)),\n        ),\n    )\n```\n\nSearch Settings\n-----\n\n## Properties Table\n\n## Fields Table for `SearchSettings`\n\n| Field                 | Type                                   | Default Value             | Description                                                                                           |\n|-----------------------|----------------------------------------|---------------------------|-------------------------------------------------------------------------------------------------------|\n| `searchEnabled`       | `Boolean`                             | `true`                    | Indicates whether the search functionality is enabled (also controles its visibility).                                               |\n| `searchProperties`    | `List\u003cKProperty1\u003cT, *\u003e\u003e`              | `emptyList()`             | A list of properties in your object to be searched.                                               |\n| `separator`           | `@Composable () -\u003e Unit`              | `{ SearchSeparator() }`   | A separator between the search and the items of the Dropdown.                         |\n| `searchIcon`          | `SearchIcon`                          | `SearchIcon()`            | Configuration for the search icon, including its appearance and behavior.                            |\n| `searchInput`         | `SearchInput`                         | `SearchInput()`           | Configuration for the search input, such as placeholders or initial text.                            |\n| `searchType`          | `SearchType`                          | `SearchType.CONTAINS`     | Defines the search type (e.g., `CONTAINS`, `STARTS_WITH`, etc.).                                      |\n| `ignoreCase`          | `Boolean`                             | `true`                    | Determines whether the search is case-insensitive.                                                   |\n| `searchActionListener`| `SearchActionListener\u003cT\u003e`             | `object : SearchActionListener\u003cT\u003e { ... }` | Listener for handling search-related actions, such as text changes or results.                       |\n\n\n\nDropdown Config\n-----\n ## Fields Table for `DropdownConfig`\n\n| Field                | Type        | Default                     | Description                                                                                      |\n|----------------------|-------------|-----------------------------|--------------------------------------------------------------------------------------------------|\n| `backgroundColor`    | `Color`     | `Color.White`               | The background color of the dropdown.                                                           |\n| `shape`              | `Shape`     | `RoundedCornerShape(20.dp)` | The shape of the dropdown, defining corner radius.                                               |\n| `maxHeight`          | `Dp`        | `300.dp`                    | Maximum height of the dropdown.                                                                 |\n| `dropdownShadow`     | `DropdownShadow` | `DropdownShadow(...)`   | Configuration for the dropdown's shadow, including its shape and elevation.                     |\n| `horizontalPadding`  | `Dp`        | `30.dp`                     | Horizontal padding inside the dropdown.                                                         |\n| `headerPlaceholder`  | `@Composable` | `{ Text(...) }`          | Composable function for the dropdown's header placeholder.                                       |\n| `withItemSelection`  | `Boolean`   | `true`                      | Indicates if item selection is enabled.                                                         |\n| `separationSpace` | `Int`  | `20`           | Space in pixels between the header and dropdown content.                                        |\n| `toggleIcon`         | `ToggleIcon` | `ToggleIcon()`             | Configuration for the dropdown toggle icon.                                                     |\n| `itemSeparator`      | `DropdownItemSeparator` | `DropdownItemSeparator()` | Configuration for separators between dropdown items.                                            |\n| `emptySearchPlaceholder` | `@Composable` | `{ EmptySearchPlaceholder() }` | Composable function displayed when no search results are found.                                 |\n| `selectItemActionListener` | `SelectActionListener\u003cT\u003e` | `object : SelectActionListener\u003cT\u003e { ... }` | Listener for handling item selection actions in the dropdown.                                   |\n\n\n\nItemContentConfig Guide\n-----\n\n\nThe ItemContentConfig class (and its subtypes) allows you to configure how items in your dropdown are displayed. Depending on your use case, you can choose:\n\nSingle Item Selection – Only one item can be chosen.\nMulti-Item Selection – Multiple items can be chosen at once.\nWithin each selection mode, there are two approaches to rendering items:\n\nDefault Content: Use a predefined layout with minimal setup.\nCustom Content: Fully control the composable layout of your items (and optionally the header).\nBelow, you’ll find an overview of each approach in a format similar to the one shown for single-item usage.\n\n## Single Item Selection\n### Default Content\nIf you want a quick, predefined appearance (title, optional subtitle, and optional icon), you can pass a DefaultDropdownItem to a Default configuration. This is the easiest way to get started—just map the fields (e.g., title, subtitle) to your data’s properties.\n\u003cimg \n    src=\"https://raw.githubusercontent.com/mejdi14/KMP-Searchable-Dropdown/main/demo/output_demo.gif\"\n    height=\"500\"\n    width=\"255\"\n    style=\"margin-right: 20px;\"\n  /\u003e\n\n``` kotlin\nval defaultConfig = SingleItemContentConfig.Default(\n    defaultItem = DefaultDropdownItem(\n        title = Person::name,\n        subtitle = Person::job,\n        withIcon = true\n    )\n)\n```\n\u003cp align=\"center\"\u003e \u003cimg src=\"https://github.com/mejdi14/KMP-Searchable-Dropdown/blob/main/demo/demo_image.jpg\" alt=\"Default Content Demo\" width=\"400\" /\u003e \u003c/p\u003e\nTip: You can hide the subtitle or the icon if you don’t need them by simply not providing those properties.\n\n### Custom Content\nFor maximum flexibility, use Custom. You’ll define a composable function for the content (how each item appears) and optionally a separate header layout (how the selected item is shown in the closed dropdown state).\n\n``` kotlin\nval customConfig = SingleItemContentConfig.Custom(\n    content = { person, _ -\u003e\n        // Define each item's row layout here\n    },\n    header = { person, _ -\u003e\n        // Define how to show the selected item in the header\n    }\n)\n```\n\nKey Point: If you omit the header parameter, it will use the same composable as content. This is perfect when you want both the dropdown items and the header to look the same.\n\n## Multi-Item Selection\n###  Default Content (Multi)\nMulti-selection also supports a Default approach. You can still provide something like a DefaultDropdownItem for consistency, but with multiple selections in mind. Additionally, you can tweak multi-selection options—such as the maximum number of items a user can select or whether to show a built-in checkbox.\n\n\u003cimg \n    src=\"https://raw.githubusercontent.com/mejdi14/KMP-Searchable-Dropdown/main/demo/output.gif\"\n    height=\"500\"\n    width=\"455\"\n    style=\"margin-right: 20px;\"\n  /\u003e\n\n``` kotlin\nval multipleDefaultConfig = MultipleItemContentConfig.Default(\n    defaultItemCustomization = DefaultDropdownItem(\n        title = Person::name,\n        subtitle = Person::job,\n        withIcon = true\n    ),\n    options = MultipleItemOptions(\n        selectionMaxCount = 3,       // For example, limit to 3 selections\n        useDefaultSelector = true    // Enable built-in checkboxes/icons\n    )\n)\n```\n\nInfo: This gives you a quick setup where each selected item is managed automatically, and the dropdown shows a checkbox or icon by default.\n\n###  Custom Content (Multi)\nWhen you need full control over each item’s layout (including how you indicate “selected” vs. “not selected”), as well as how selected items appear in the header, choose Custom.\n\n``` kotlin\nval multipleCustomConfig = MultipleItemContentConfig.Custom(\n    content = { person, isSelected, multipleSelectActionListener -\u003e\n        // Define how each item row should look,\n        // and call `onSelect` or `onDeselect` on click.\n    },\n    header = { person, selectedPerson, removeItemListener -\u003e\n        // Define how each selected item appears\n        // in the header (e.g. chips or horizontal list).\n    },\n    options = MultipleItemOptions(\n        selectionMaxCount = 5,\n        useDefaultSelector = false\n    )\n)\n```\n\n\n\nYou receive isSelected for each item, so you can visually reflect the selection state.\n\nThe multipleSelectActionListener helps you handle toggling (select/deselect) with a simple function call.\n\nThe header composable is called for each selected item if you want to display them (like chips or icons) above the list.\nExtras: MultipleItemOptions\nFor multi-selection specifically, the options parameter lets you control various behaviors:\n\nselectionMaxCount: Prevents users from selecting more than a certain number of items.\nuseDefaultSelector: Adds a built-in checkbox or icon next to each item.\ndefaultSelectorPosition: Positions that icon on the start or end of the item row.\ndefaultCheckboxParams: Styles the checkbox if useDefaultSelector is true.\n\n## Upcoming Features\n\nHere's what's coming next:\n\n### 🔜 Animations\n\nIf you have suggestions or feature requests, feel free to open an issue or contribute to the repository.\n\n\n## 🤝 Contributing\n\nContributions, issues and feature requests are welcome.\u003cbr /\u003e\nFeel free to check [issues page] if you want to contribute.\u003cbr /\u003e\n\n## Author\n\n👤 **Mejdi Hafiane**\n\n- profile: [@MejdiHafiane](https://twitter.com/mejdi141)\n\n## Show your support\n\nPlease ⭐️ this repository if this project helped you!\n\n## 📝 License\n\nCopyright © 2019 [Mejdi Hafiane](https://github.com/mejdi14).\u003cbr /\u003e\nThis project is [MIT](https://github.com/mejdi14/readme-md-generator/blob/master/LICENSE) licensed.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmejdi14%2Fkmp-searchable-dropdown","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmejdi14%2Fkmp-searchable-dropdown","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmejdi14%2Fkmp-searchable-dropdown/lists"}