KeepNeeds Refinement
Select Component link

A trigger field that opens a Select Group of options. 16 variants across Type (Default/Peso) × State (Default/Expanded/Error/Disabled) × isFilled. Composes a Select Field trigger with a Select Group menu.

Rebuilt — schema is clean
The v2.0 rebuild added State=Disabled, dropped the product-specific Mobile variant, and now composes Select Field + Select Group. v2.1 finished the schema: isFilled renamed to true/false to agree with the Select Field it wraps, State=Active renamed Expanded, and the redundant isSelected removed. The matrix is a clean Type (2) × State (4) × isFilled (2) = 16 with no correlated axes. No pressed state is correct — form fields use Expanded for interaction feedback, not pressed.

Contexts are illustrative. Final screens will reference actual GCash patterns.

Select Option
LabelSelect option
Properties
variant
type
Reusable
Pass
The product-specific Mobile (phone input) variant is gone — Type is now just Default / Peso, so the component is a generic select usable across flows. Peso remains a GCash currency affordance but is a thin content variation, not a bundled feature.
Self-contained
Pass
Bundles the trigger field, chevron affordance, and the menu overlay. Every state — Default, Active, Error, Disabled — is self-contained with token-bound fills and borders.
Consistent
Pass
Three orthogonal props — Type × State × isFilled — with no redundant or correlated axis. isFilled uses lowercase true/false, agreeing with the Select Field it nests and the DS-wide standard, and State=Expanded names the open menu literally rather than the ambiguous "Active".
Composable
Pass
Now composes properly — every variant nests a Select Field trigger instance and a Select Group menu instance rather than hand-building either. The Mobile variant's bundled phone input has been extracted.
State iOS Android Figma Property Notes
Default Yes Yes State=Default Gray #D7E0EF border, white bg, chevron down. Resting state, menu closed.
Expanded Yes Yes State=Expanded Blue #005CE5 border, chevron up, Select Group menu open beneath. This is also the tap feedback — the field goes straight from Default to Expanded on tap.
Error Yes Yes State=Error Red border — weak #F4C7C9 collapsed, strong #D61B2C when expanded. Orthogonal to whether a value is filled.
Disabled Yes Yes State=Disabled Non-interactive; the menu cannot open. Added in v2.0 for conditional form flows (e.g. "Country" locked until "Region" is picked).
Filled vs empty Yes Yes isFilled Whether the field shows a chosen value or placeholder text. Composes with every State.
Pressed N/A N/A Not modelled by design. Select is a form field, not a button — the field family (Select Field, Recipient Field) uses Expanded / active-style feedback rather than a pressed state.
  • Code Connect mappings not registered. The DropdownItem boolean issue is resolved (Select Item now ships lowercase true/false). Still blocked on the trigger's own state coverage and on the native library existing — the snippets remain a Planned API. C7 · Code Connect Linkability
  • v2.0: State=Pressed deliberately not modelled — reviewed and confirmed correct. Select belongs to the form-field family (Select Field, Recipient Field), whose convention is Default / Active / Error / Disabled with no pressed state; buttons and list rows use pressed, fields use active. Tapping a Select transitions straight to Active (blue border, menu open), which is the tap feedback — a pressed frame would be a transient flash between the two. (C5)
  • v2.1: isFilled values renamed no/yesfalse/true across all 16 variants — Select now agrees with the Select Field it nests and with the DS-wide boolean standard. (C2)
  • v2.1: State=Active renamed to Expanded — the state is named for what it is, the open menu. (C2)
  • v2.1: Redundant isSelected property removed — it was perfectly correlated with the old State=Active and contributed no combinations. The matrix is unchanged at 16 variants (Type 2 × State 4 × isFilled 2), with no collisions. (C2)
  • v2.1: isFilled confirmed as a genuine property, not redundant like isSelected — it varies independently against every State, controlling whether the field shows a chosen value or placeholder text. Retained deliberately. (C2)
  • v2.1: Peso Sign shape_full BOOLEAN_OPERATION deliberately not tracked here — owned by the iconography team and handled at the icon-library level. The same node appears in Select Item's Leading slot, so the flattened vector will land across both components at once. Not a Select defect. (C6)
  • Register Code Connect mapping to EBSelect. With the schema settled — Type × State × isFilled, no redundant axis — wire the Figma properties 1:1 to the SwiftUI / Compose API, forwarding State and isFilled down to the nested EBSelectField and the menu to EBSelectGroup. Docs
  • Rename isFilled values to true/false. v2.1: Applied — all 16 variants now read isFilled=false/true, matching the nested Select Field it wraps and the wider form-field family. The parent no longer disagrees with its own child. Rename
  • Rename State=Active to Expanded. v2.1: Applied — the state now names what it is (the open menu) rather than the ambiguous "Active", which read as focused or enabled. Frees Active should a focus state ever be needed. Rename
  • Drop isSelected and derive it from State. v2.1: Applied — the redundant property is gone. The matrix is now a clean Type (2) × State (4) × isFilled (2) = 16 with no correlated axis, and Code Connect has one less prop to map. Property
  • Add a Disabled state to the variant matrix. v2.0: Applied — State=Disabled ships across all four Type × isFilled combinations, so conditional form flows (e.g. "Country" locked until "Region" is picked) no longer need an opacity hack on the parent frame. State
  • Extract Mobile variant into a dedicated component. v2.0: Applied — the Mobile (phone input) variant is gone. Type is now just Default / Peso, so the base component no longer carries country-code logic. Family
  • Rename type to isExpanded. v2.0: Superseded by the restructure — type no longer encodes expansion. Type now means content type (Default / Peso) and the open menu is State=Active, so the keyword clash the rename was avoiding is gone. (See the open issue on renaming ActiveExpanded.) Rename
  • Rename DropdownItem selected values to true/false. v2.1: Applied on the item — Select Item (the rebuilt DropdownItem) now ships lowercase true/false across all 36 variants, matching the C2 rule and Radio Button. The string-to-bool conversion layer is gone. Rename
  • Add a selected-visual state to DropdownItem. v2.0: Applied on the item — Select Item's isSelected=true flips the label to brand #005CE5 and exposes a checkmark via the Trailing icon slot, so a picked row is unambiguous. State
Variants
Text
DES DEV

Default text dropdown. Label header, select trigger with placeholder text and chevron, optional subtext. Used for general-purpose list selection.

LabelSelect option
Properties
Variant
Type
Properties
Variant Text
Type Collapsed
Colors
Bg #FFFFFF
Border #D7E0EF
Value #0A2757
Icon #005CE5
Placeholder #90A8D0
Layout
Field height 48px
Padding H 12px
Padding V 14px
Border radius 6px
Border 1px solid
Icon size 20 × 20
Typography
Text Style Primary/Label/Light/Small
Font Proxima Soft Semibold
Size 14px
Tracking 0.25px
Line-height 14px
Colors by State

Trigger field and dropdown list colors. Border color is the primary state indicator. Error variant uses distinct border tokens.

Role Token DEFAULTACTIVEERROR (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
DES DEV

Error state dropdown with red border. Collapsed uses weak border (#F4C7C9), expanded uses strong border (#D61B2C). Subtext turns red for error messaging.

LabelSelect option
Properties
Variant
Type
Properties
Variant Error
Type Collapsed
Colors
Bg #FFFFFF
Border #F4C7C9
Value #0A2757
Icon #005CE5
Layout
Field height 48px
Padding H 12px
Padding V 14px
Border radius 6px
Border 2px solid
Icon size 20 × 20
Typography
Text Style Primary/Label/Light/Small
Font Proxima Soft Semibold
Size 14px
Tracking 0.25px
Line-height 14px
Layout
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
DES DEV

Amount selection with peso sign prefix. Same trigger structure as Text but with a currency indicator for monetary value selection.

LabelSelect option
Properties
Variant
Type
Properties
Variant Amount
Type Collapsed
Colors
Bg #FFFFFF
Border #D7E0EF
Value #0A2757
Icon #005CE5
Peso sign #183462
Placeholder #90A8D0
Layout
Field height 48px
Padding H 12px
Padding V 14px
Border radius 6px
Border 1px solid
Icon size 20 × 20
Peso sign size 15 × 15
Typography
Text Style Primary/Label/Light/Small
Font Proxima Soft Semibold
Size 14px
Tracking 0.25px
Line-height 14px
Typography
Role Token FontSizeTrackingLine-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
Mobile
DES DEV

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.

LabeliSelect option+63XXX XXX XXXX
Properties
Variant
Type
Properties
Variant Mobile
Type Collapsed
Colors
Bg #FFFFFF
Border #D7E0EF
Value #0A2757
Icon #005CE5
Placeholder #90A8D0
Layout
Field height 48px
Padding H 12px
Padding V 14px
Border radius 6px
Border 1px solid
Icon size 20 × 20
Typography
Text Style Primary/Label/Light/Small
Font Proxima Soft Semibold
Size 14px
Tracking 0.25px
Line-height 14px

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 PropertySwiftUICompose
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?
SwiftUI
ios/Components/Dropdown/EBDropdown.swift
Jetpack Compose
android/components/dropdown/EBDropdown.kt
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
)
RequirementiOSAndroid
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.

varianttypeNode ID
TextCollapsed18482:31966
TextExpanded18482:31960
ErrorCollapsed18482:31955
ErrorExpanded18482:31949
AmountCollapsed18482:31944
AmountExpanded18482:31938
MobileCollapsed18482:31911
MobileExpanded18482:31924
Initial Assessment · node 18482:31910
Component assessed — 8 variants documented across variant (Text/Error/Amount/Mobile) × type (Collapsed/Expanded). Generic dropdown with trigger field, chevron affordance, and overlay item list. Documented
Initial
DropdownItem selected uses yes/noselected=yes/no instead of true/false. Incompatible with Swift Bool and Kotlin Boolean for Code Connect mapping. Open
C2 Open
Missing disabled and pressed states — Only Collapsed, Expanded, and Error states defined. No disabled state for non-interactive forms, no pressed state for touch feedback. Open
C5 Open
Amount variant Peso Sign uses BOOLEAN_OPERATIONshape_full is a BOOLEAN_OPERATION, not a clean vector path. May render inconsistently on native platforms. Open
C6 Open
Code Connect mappings — No CLI mappings registered yet. Open
C7 Open