A trigger button that opens a popover surface containing selectable options.
selected uses yes/no instead of true/false (C2). Amount variant Peso Sign uses BOOLEAN_OPERATION (C6).Contexts are illustrative. Final screens will reference actual GCash patterns.
selected uses yes/no string instead of true/false boolean (C2). Property type is a generic name — could conflict with platform keywords. Layer dropdowncontainer inconsistent with kebab-case convention.| State | iOS | Android | Figma Property | Notes |
|---|---|---|---|---|
| Collapsed (Default) | Yes | Yes | type=Collapsed | Gray #D7E0EF border, white bg. Chevron down. |
| Expanded (Active) | Yes | Yes | type=Expanded | Blue #005CE5 border, chevron up. Dropdown list overlay with shadow. |
| Error | Yes | Yes | variant=Error | Red border — weak #F4C7C9 (collapsed), strong #D61B2C (expanded). |
| Disabled | No | No | — | Not defined. Required for form accessibility. |
| Pressed | No | No | — | Not defined. Touch feedback expected on mobile. |
- DropdownItem
selectedusesyes/nostrings. Should betrue/falsefor direct SwiftBool/ KotlinBooleanmapping in Code Connect. C2 · Variant & Property Naming - No disabled state. Form dropdowns must support a non-interactive state for accessibility and conditional form flows (e.g. "Country" disabled until "Region" is picked). C5 · Interaction State Coverage
- No pressed state. Touch feedback is expected on both platforms — iOS highlight, Android ripple. Currently consumers improvise this. C5 · Interaction State Coverage
- Peso Sign uses a
shape_fullBOOLEAN_OPERATION. Not a clean vector path — renders inconsistently across SVG export and native platforms. Flatten to a single path. C6 · Asset & Icon Quality - Code Connect mappings not registered. Blocked until the boolean and state issues above are resolved. C7 · Code Connect Linkability
- Add a
Disabledstate to the variant matrix. Required for form accessibility and conditional logic — without it, consumers hack opacity filters on the parent frame. State - Rename
typetoisExpanded. Avoids platform keyword conflicts (typeis reserved in many languages) and aligns with boolean naming convention. Rename - Rename DropdownItem
selectedvalues totrue/false. Direct boolean mapping eliminates the string-to-bool conversion layer when wiring Code Connect. Rename - Extract Mobile variant into a dedicated
CountryCodeDropdown. It bundles too many concerns (dropdown + phone input) for a generic dropdown and forces the base component to carry country-specific logic. Family - Add a selected-visual state to DropdownItem. Checkmark or background highlight makes the current selection unambiguous — today the open menu looks the same whether an item is picked or not. State
Default text dropdown. Label header, select trigger with placeholder text and chevron, optional subtext. Used for general-purpose list selection.
Trigger field and dropdown list colors. Border color is the primary state indicator. Error variant uses distinct border tokens.
| Role | Token | DEFAULT | ACTIVE | ERROR (collapsed) | ERROR (expanded) |
|---|---|---|---|---|---|
| Trigger border | selected-field/color/{state}/border | #D7E0EF | #005CE5 | #F4C7C9 | #D61B2C |
| Trigger bg | selected-field/color/{state}/bg | #FFFFFF | #FFFFFF | #FFFFFF | #FFFFFF |
| Placeholder | selected-field/color/{state}/placeholder | #90A8D0 | #90A8D0 | #90A8D0 | #90A8D0 |
| Chevron icon | selected-field/color/{state}/icon | #005CE5 | #005CE5 | #005CE5 | #005CE5 |
| Peso sign (Amount) | selected-field/color/{state}/icon-currency | #183462 | #183462 | – | – |
| Header label | formgroup-header/color/label | #0A2757 | #0A2757 | #0A2757 | #0A2757 |
| Item label | dropdown-item/color/default/label | – | #0A2757 | – | #0A2757 |
| Item border | dropdown-item/color/default/border | – | #E5EBF4 | – | #E5EBF4 |
| Dropdown bg | bg/color-bg-main | – | #FFFFFF | – | #FFFFFF |
| Subtext | text/color-text-weak | #445C85 | #445C85 | – | – |
| Error subtext | border/color-border-destructive | – | – | #D61B2C | #D61B2C |
Error state dropdown with red border. Collapsed uses weak border (#F4C7C9), expanded uses strong border (#D61B2C). Subtext turns red for error messaging.
| Role | Token |
|---|---|
| Trigger height | 46px |
| Corner radius | 6px (radius-2) |
| Trigger padding | 6px top, 8px bottom, 12px horizontal |
| Chevron size | 32 × 32 |
| Peso sign size (Amount) | 15 × 15 |
| Item padding | 16px vertical, 12px left, 16px right |
| Dropdown corner radius | 6px |
| Dropdown shadow | 0 6px 12px rgba(2,14,34,0.16) |
| Header padding bottom | 8px |
Amount selection with peso sign prefix. Same trigger structure as Text but with a currency indicator for monetary value selection.
| Role | Token | Font | Size | Tracking | Line-height |
|---|---|---|---|---|---|
| Header label | Primary/Label/Light/Small | Proxima Soft Semibold | 14px | 0.25px | 14px |
| Trigger placeholder | Primary/Label/Light/Small | Proxima Soft Semibold | 14px | 0.25px | 14px |
| Dropdown item | Primary/Label/Light/Large | Proxima Soft Semibold | 18px | 0.25px | 18px |
| Subtext | — | BarkAda Semibold | 12px | 0px | 18px |
Country code dropdown with phone number input. Bundles a label row (with info icon), a select field for country code, and a Labeled Field for phone number entry. Product-specific to GCash mobile number flows.
iOS — Swift Package Manager
// In Xcode: File → Add Package Dependencies "https://github.com/AY-Org/eb-ds-ios"
Android — Gradle (Kotlin DSL)
dependencies { implementation("com.eastblue.ds:dropdown:1.0.0") }
Import
import EastBlueDS // SwiftUI import com.eastblue.ds.dropdown.* // Compose
Package not yet published. These are the planned distribution paths.
| Figma Property | SwiftUI | Compose |
|---|---|---|
| variant = Text | EBDropdown(label:items:) | EBDropdown(label, items) |
| variant = Error | .ebError(true) | isError = true |
| variant = Amount | .ebStyle(.amount) | style = EBDropdownStyle.Amount |
| variant = Mobile | .ebStyle(.mobile) | style = EBDropdownStyle.Mobile |
| type = Collapsed | — | — |
| type = Expanded | isPresented: Binding<Bool> | expanded: Boolean |
| subtext (boolean) | helperText: String? | helperText: String? |
EBDropdown("Category", selection: $category) { ForEach(categories) { item in Text(item.name) } }
EBDropdown( label = "Category", items = categories, selectedItem = selected, onItemSelected = { selected = it } )
EBDropdown("Category", selection: $category) { ForEach(categories) { item in Text(item.name) } } .ebError(true) .ebHelperText("Please select a category")
EBDropdown( label = "Category", items = categories, selectedItem = selected, onItemSelected = { selected = it }, isError = true, helperText = "Please select a category" )
EBDropdown("Amount", selection: $amount) { ForEach(amounts) { item in Text(item.formatted) } } .ebStyle(.amount)
EBDropdown( label = "Amount", items = amounts, selectedItem = selected, onItemSelected = { selected = it }, style = EBDropdownStyle.Amount )
| Requirement | iOS | Android |
|---|---|---|
| Minimum touch target | 44 × 44 pt | 48 × 48 dp |
| Accessibility label | .accessibilityLabel("Select category") | contentDescription |
| Role | .accessibilityAddTraits(.isButton) | semantics { role = Role.DropdownList } |
| Expanded state | VoiceOver: "collapsed" / "expanded" | TalkBack: announce expansion state |
| Item selection | .accessibilityValue(selectedItem) | semantics { stateDescription } |
Do
Use Dropdown for selecting from a predefined list of options. Label the trigger clearly so users know what they're selecting.
Don't
Use Dropdown for free-text entry — use Input Field instead. Dropdown is for constrained selection only.
Do
Show error state with helper text below the field explaining the validation issue.
Don't
Use the Mobile variant for generic dropdown needs — it bundles phone-specific UI that adds complexity without value.
| ID | Criterion | Status | Notes |
|---|---|---|---|
| C1 | Layer Structure & Naming | Ready | Semantic names: label, container, text-container, peso-sign, Chevron Up/Down. Minor: dropdowncontainer missing separator. |
| C2 | Variant & Property Naming | Needs Refinement | DropdownItem selected uses yes/no instead of true/false. type is a generic property name. |
| C3 | Token Coverage | Ready | All colors bound to design tokens. Space, radius, typography, and elevation tokens all present. |
| C4 | Native Mappability | Needs Refinement | Text/Error/Amount map to Menu (iOS) / ExposedDropdownMenuBox (Android). Mobile variant needs custom composition. |
| C5 | Interaction State Coverage | Requires Rework | Missing disabled and pressed states. Only Collapsed, Expanded, and Error defined. |
| C6 | Asset & Icon Quality | Needs Refinement | Chevrons are vector instances. Amount variant Peso Sign uses BOOLEAN_OPERATION (shape_full). |
| C7 | Code Connect Linkability | Needs Refinement | No CLI mappings registered yet. |
| Aspect | Status | Notes |
|---|---|---|
| Property naming | Needs Refinement | DropdownItem selected needs boolean rename; type is generic |
| Asset quality | Needs Refinement | Peso Sign BOOLEAN_OPERATION in Amount variant |
| State coverage | Requires Rework | Missing disabled/pressed states blocks complete mapping |
| Native component file | Needs Refinement | EBDropdown.swift / EBDropdown.kt not yet created |
4 variant values × 2 type values (Collapsed/Expanded). subtext boolean toggleable on all variants.
| variant | type | Node ID |
|---|---|---|
| Text | Collapsed | 18482:31966 |
| Text | Expanded | 18482:31960 |
| Error | Collapsed | 18482:31955 |
| Error | Expanded | 18482:31949 |
| Amount | Collapsed | 18482:31944 |
| Amount | Expanded | 18482:31938 |
| Mobile | Collapsed | 18482:31911 |
| Mobile | Expanded | 18482:31924 |
selected=yes/no instead of true/false. Incompatible with Swift Bool and Kotlin Boolean for Code Connect mapping.
Openshape_full is a BOOLEAN_OPERATION, not a clean vector path. May render inconsistently on native platforms.
Open