feat(dropdown): add single-choice dropdown bubble component#1002
Open
ShaySapozhnikov wants to merge 1 commit into
Open
feat(dropdown): add single-choice dropdown bubble component#1002ShaySapozhnikov wants to merge 1 commit into
ShaySapozhnikov wants to merge 1 commit into
Conversation
Introduces a focusable dropdown with keyboard navigation, selection messages, runtime option updates, and a demo example with VHS recording. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds a new dropdown bubble — a single-choice, keyboard-driven select control for Bubble Tea v2 applications. It follows the same Model–Update–View conventions as the other Bubbles components (
textinput,table,list, etc.) and integrates with the existingkeyandhelppackages.What it does
The dropdown renders a bordered header showing either:
Select…) when nothing is selected, orWhen focused and expanded, a vertical list of options appears below the header. The user navigates with arrow keys (or
j/k), confirms with Enter, or dismisses with Esc without changing the selection.Three visual states are supported for the header:
Focus()called, not disabled212)Blur()240)Disabled = true238)Collapsed headers show a
▶indicator; expanded headers show▼.Architecture
Core types
OptionEach selectable item has a display Label and a semantic Value (they may differ, e.g.
"English"/"en"):ModelThe component model holds configuration, internal state, and styling:
KeyMaphelp.KeyMap)StylesPlaceholderMaxVisible6); longer lists scrollDisabledtrue, ignores input and usesDisabledHeaderstyleoptionscursorselected-1= none)openfocusscrollOffsetwidthConstruction (
New+ option funcs)Configure at creation time with functional options:
Defaults: width
20, placeholderSelect…,MaxVisible6, no selection.Focus management
The parent model is responsible for routing keyboard messages to the focused dropdown and for focus switching between multiple dropdowns:
Only focused, non-disabled models process key input in
Update.Update loop behavior
When collapsed (
open == false):len(options) > 0)When expanded (
open == true):↑/k↓/jSelectMsgCloseMsgScrolling: when
len(options) > MaxVisible,scrollOffsetadjusts automatically so the cursor stays within the visible window (clampScrollOffset).When disabled or unfocused: all input is ignored.
When empty options: the placeholder is shown and the list never opens.
Messages emitted to the parent
Parent models should type-switch on these in their own
Update:Example handling:
Commands are returned as
tea.Cmdclosures that produce these messages, matching Bubble Tea conventions.Runtime mutation
SetOptionsshould be called while collapsed (the example guards with!dd.IsOpen()).Rendering (
View)Returns a multi-line string:
Styles are fully customizable via
StylesandDefaultStyles().Key map & help integration
KeyMapimplementshelp.KeyMap(ShortHelp/FullHelp) so it works with thehelpbubble out of the box:Customize with
WithKeyMapor by mutatingm.KeyMapafter construction.Example program
A full demo lives at
examples/dropdown/main.go. It showcases three dropdowns side by side:rkey swaps Charm projects → programming languages)Run it:
Controls:
Full source:
examples/dropdown/main.goDemo recording
The GIF above was generated with VHS from
dropdown/demo.tape. Reproduce it:Test plan
go test ./dropdown/...— 20+ unit tests covering focus/blur, open/close, navigation, selection messages, scrolling, disabled/empty states, and view renderinggo run ./examples/dropdown— manual smoke test of multi-dropdown focus, selection, reload, disabled, and empty behaviorsMade with Cursor