Bubble plugins
Modern Dropdown for Bubble
Configure the Modern Dropdown Bubble plugin for search, single or multiple selection, rich option rows, and native anchored placement.
Modern Dropdown is a Bubble element for searchable single and multiple selection. It uses the browser’s HTML Popover API and CSS Anchor Positioning. The option panel enters the browser top layer, so an overflow: hidden group does not clip it.
Version 0.2.0 is private. An app must be authorized for the plugin before it can install the current version.
Browser requirements
Modern Dropdown targets current browsers with native support for:
There is no polyfill, portal, or JavaScript coordinate fallback. Test the browsers your app supports before replacing an existing dropdown.
Add the element
- Install Modern Dropdown in the Bubble app.
- Place the Modern Dropdown element on the page.
- Set Options JSON to a JSON array.
- Set Return data type if the values represent Bubble Things.
- Choose single or multiple selection.
- Read the element’s states or respond to its events in Bubble workflows.
Configuration reference
| Property | Default | Use |
|---|---|---|
| Options JSON | Two example options | JSON array containing the available options and groups. |
| Default value | Empty | One option value restored by Reset in single-selection mode. |
| Return data type | Not set | Bubble data type represented by option values. |
| Placeholder | Select an option |
Text shown when nothing is selected. |
| Allow multiple selections | No | Enables removable chips and list selection. |
| Default values | Empty list | Option values restored by Reset in multiple-selection mode. |
| Searchable | Yes | Shows the search input and enables filtering. |
| Clearable | Yes | Lets the user clear the current selection from the control. |
| Input is disabled | No | Prevents opening, searching, and selecting when set to Yes. |
| No-results text | No results |
Message shown when the search has no matches. |
| Accessible label | Dropdown |
Purpose announced by screen readers. Use a field-specific label. |
| Preferred placement | Auto |
First side the browser tries for the panel. |
A basic option needs text and value:
[
{"text": "Planned", "value": "planned"},
{"text": "In progress", "value": "in-progress"},
{"text": "Blocked", "value": "blocked", "disabled": true},
{"text": "Done", "value": "done"}
]
text is the visible label and the main accessible name. value is the stable value published to Bubble. Values must be unique after conversion to text.
Option fields
| Field | Required | Purpose |
|---|---|---|
text |
Yes | Visible label, search text, and accessible option name. label is accepted as an alias. |
value |
Yes | Stable value published in the selection states. |
disabled |
No | Set to true to show an option without allowing selection. |
keywords |
No | A list of extra search terms. |
image |
No | An HTTP, HTTPS, or protocol-relative image URL. It can also be an object with src and alt. |
secondaryText |
No | Supporting text shown below the main label. secondary_text and description are accepted aliases. |
badge |
No | Short text displayed beside the option. |
The plugin creates DOM nodes and assigns text content. It does not interpret labels, secondary text, or badges as HTML.
Groups
Group options with a parent object containing label and options:
[
{
"label": "Active",
"options": [
{"text": "Planned", "value": "planned"},
{"text": "In progress", "value": "in-progress"}
]
},
{
"label": "Finished",
"options": [
{"text": "Done", "value": "done"}
]
}
]
This shape is compatible with existing 1T Dropdown and SlimSelect-style grouped data.
Rich options
Use the fixed presentation fields when a plain label is not enough:
[
{
"text": "Maya Chen",
"value": "user-id",
"image": {
"src": "https://example.com/maya.jpg",
"alt": "Maya Chen"
},
"secondaryText": "Product design",
"badge": "Owner",
"keywords": ["design", "admin"]
}
]
If an image is missing or cannot load, the plugin shows initials. Use Item image size, Item image shape, and Item image fit to control image presentation.
Bubble Things
Set Return data type when each option represents a Bubble Thing. Put the Thing’s unique ID in value:
[
{"text": "Maya Chen", "value": "1680000000000x123456789012345678"}
]
The selected_option and selected_options states then return Things of that type. The text-based states still expose the matching IDs and labels.
Single and multiple selection
Single selection is the default. Set Default value to one option value.
Turn on Allow multiple selections to select more than one option. Selected items appear as removable chips, and the panel stays open while the user toggles options. Set Default values to a Bubble list of text values. A nonempty Default values list takes priority over Default value.
Selection order follows the source order in Options JSON, not the order in which the user clicked the options. The singular states expose the first selected option so workflows built for single selection keep a predictable value.
Placement
Preferred placement accepts Auto, Down, Up, Right, or Left.
| Setting | Placement order |
|---|---|
Auto |
Down, Up, Right, Left |
Down |
Down, then Up |
Up |
Up, then Down |
Right |
Right, then Left |
Left |
Left, then Right |
The browser chooses the first placement that fits. Every direction keeps a 4 pixel gap between the control and the panel. The panel remains in the top layer for every placement.
States
| State | Type | Meaning |
|---|---|---|
selected_option |
Return data type | First selected Bubble Thing. |
selected_value |
text | Value of the first selected option. |
selected_label |
text | Label of the first selected option. |
selected_options |
list of Return data type | All selected Bubble Things in option-source order. |
selected_values |
list of text | All selected values in option-source order. |
selected_labels |
list of text | All selected labels in option-source order. |
selection_count |
number | Number of selected options. |
search_term |
text | Current search input. |
is_open |
yes/no | Whether the panel is open. |
is_disabled |
yes/no | Current disabled status. |
error_message |
text | The latest options validation error, or empty text when valid. |
Events
- Selection changed runs after the selected values change.
- Selection cleared runs when the selection becomes empty.
- Opened and Closed track panel visibility.
- Search changed runs when the user changes the filter text.
- Invalid options received runs when Options JSON cannot be normalized.
Actions
| Action | Use |
|---|---|
| Set selected value | Replace the current single selection with one value. |
| Set selected values | Replace the current selection with a list of values. |
| Add selected value | Add one value in multiple-selection mode. |
| Remove selected value | Remove one value in multiple-selection mode. |
| Clear selection | Remove every selected value. |
| Open | Open the option panel. |
| Close | Close the option panel. |
| Focus | Move keyboard focus to the control. |
| Reset | Restore Default value or Default values. |
Values that do not exist in the current options are ignored. When options change, the plugin keeps selected values that still exist and removes stale ones.
Search and keyboard use
Search matches the label, value, secondary text, badge, and keywords. Matching ignores case and combining accents.
The element uses combobox and listbox semantics. Users can move through enabled options with the arrow keys, select with Enter, close with Escape, and clear or edit search text with the normal text-input keys. Set Accessible label to the field’s purpose, such as Status or Assignee.
Styling
| Style property | Default | Choices or purpose |
|---|---|---|
| Background color | rgba(255,255,255,1) |
Control background. |
| Border color | rgba(9,23,71,0.2) |
Control and panel border. |
| Border width | 1px |
0px, 1px, 2px, 3px, or 4px. |
| Border radius | 6px |
0px, 2px, 4px, 6px, 8px, 12px, 16px, or 999px. |
| Placeholder color | rgba(9,23,71,0.45) |
Placeholder text. |
| Focus color | rgba(59,130,246,0.65) |
Keyboard and pointer focus ring. |
| Active option background | rgba(59,130,246,0.1) |
Keyboard-highlighted option. |
| Selected option background | rgba(59,130,246,0.16) |
Selected option row. |
| Disabled background | rgba(9,23,71,0.05) |
Disabled control and option background. |
| Disabled text color | rgba(9,23,71,0.35) |
Disabled text. |
| Item image size | 28px |
20px, 24px, 28px, 32px, or 40px. |
| Item image shape | Circle |
Circle, Rounded, or Square. |
| Item image fit | Cover |
Cover or Contain. |
| Secondary text color | rgba(9,23,71,0.6) |
Supporting option text. |
| Badge background | rgba(9,23,71,0.08) |
Rich-option badge background. |
| Badge text color | rgba(9,23,71,1) |
Rich-option badge text. |
| Multi-select chip background | rgba(59,130,246,0.12) |
Selected chip background. |
| Multi-select chip text color | rgba(9,23,71,1) |
Selected chip text. |
The runtime renders inside Shadow DOM. Page-level CSS should not target the plugin’s internal classes. Use the Bubble style properties instead.
Errors and current limits
Invalid JSON, duplicate values, missing labels, and missing values populate error_message and trigger Invalid options received. Keep the last error visible during development rather than hiding it with a workflow.
Version 0.2.0 does not include remote search, user-created options, virtualization, arbitrary option markup, or a legacy-browser positioning fallback.
The private Bubble demo contains single-select, multiple-select, placement, clipping, and rich-option examples. Access is limited to authorized testers.