A 32px pill used for filters, tags, selected values, and pill-styled dropdown triggers.
style (filled/light/outline), leading (none/avatar/icon), and trailing (none/close/chevron) slot props. Fixes the paradigm mismatch, collapses 8 variants into cleaner prop combinations, and aligns with native chip APIs.Contexts are illustrative. Final screens will reference actual GCash patterns.
type + with icon (yes/no). Dropdown uses type=default/"with active time". C2icon-placeholder), not an Avatar instance or swappable Icon. Breaks compositional inheritance. C6| State | iOS | Android | Figma Property | Notes |
|---|---|---|---|---|
| Active / Selected | Yes | Yes | Filter · type=primary | Filled blue background, white label. Used when a filter is applied. |
| Inactive (light) | Yes | Yes | Filter · type=light | Light gray pill, gray label. Used for unapplied filters or tag readouts. |
| Inactive (outline) | Yes | Yes | Filter · type=outline | White pill, gray border, gray label. |
| Dropdown trigger | Yes | Yes | Filter w/ Dropdown · default | Light style with chevron. Used for sort/filter pickers. |
| Pressed / Disabled / Error | N/A | N/A | — | Not defined in Figma. C5 |
- Filter Two separate Figma components share the same pill anatomy — (6 variants) and Filter with Dropdown (2 variants). Should consolidate into a single Chip with
style,leading, andtrailingslot props. C2 - Boolean property
with iconusesyes/noinstead oftrue/false. Incompatible with SwiftBool/ KotlinBoolean. C2 - Enum value
"with active time"contains spaces and a nonsensical name — should bewithValue/hasSelectedValueor collapse into aselectedValueoptional string prop. C2 - Leading slot is a hardcoded 24px gray circle (
icon-placeholder) — should be a swappable Avatar or Icon instance via instance swap. C6 - No pressed / selected / disabled / error states documented. C5
- Code Connect CLI mappings not registered. C7
- Rename "Filter" → "Chip" and merge with "Filter with Dropdown" into one component. Matches industry terminology (Material FilterChip/InputChip, Polaris Tag, Carbon Tag). Docs
- Replace the property schema with three semantic slot props:
style(filled / light / outline),leading(none / avatar / icon),trailing(none / close / chevron). Plus optionalselectedValuestring for the "Sort by X" pattern. Property - Replace the leading placeholder with a real slot — instance-swap an Avatar (for person filters) or Icon (for category filters). Slot
- Add pressed / disabled states so applied-filter chips have a documented pressed affordance and disabled filters have a defined appearance. State
Brand blue fill with white label. Represents an active/applied filter.
Three style modes, each with bg, label, and icon tokens. Dropdown adds label-link and chevron.
| Role | Token | Token | Value |
|---|---|---|---|
| Filled | bg | main/filter/color/primary/bg | #005CE5 |
| — | label | main/filter/color/primary/label | #FFFFFF |
| — | icon | main/filter/color/primary/icon | #F6F9FDB8 |
| Light | bg | main/filter/color/secondary/bg | #EEF2F9 |
| — | label | main/filter/color/secondary/label | #6780A9 |
| — | icon | main/filter/color/secondary/icon | #7E96BE |
| — | selected value | main/filter/color/secondary/label-link | #005CE5 |
| — | chevron | main/filter/color/secondary/chevron | #005CE5 |
| Outline | border | main/filter/color/tertiary/border | #D7E0EF |
| — | label | main/filter/color/tertiary/label | #6780A9 |
| — | icon | main/filter/color/tertiary/icon | #7E96BE |
Light gray fill with gray label. Used for inactive filters, tags, or dropdown trigger base.
White fill with 2px gray border and gray label. Alternative inactive style for light surfaces.
Light style with a trailing chevron. Used as a pill-styled dropdown trigger. Selected value shown in blue <code>label-link</code>.
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:chip:1.0.0") }
| Figma Property | SwiftUI | Compose |
|---|---|---|
| style | .ebStyle(.filled / .light / .outline) | style = EBChipStyle.* |
| leading | leading: EBChipLeading? | leading: @Composable (() -> Unit)? |
| trailing | trailing: EBChipTrailing? | trailing: EBChipTrailing? |
| selectedValue | selectedValue: String? | selectedValue: String? |
| label | title: String | label: String |
| onTap / onClose | action / onRemove | onClick / onRemove |
// Applied filter — brand fill, avatar + close EBChip("Filter Name", leading: .avatar(EBAvatar(initials: "DM")), trailing: .close, onRemove: { /* remove filter */ }) .ebStyle(.filled) // Inactive filter — light, label only EBChip("Category") .ebStyle(.light) // Dropdown trigger with selected value EBChip("Sort by", selectedValue: "Conservative first", trailing: .chevron, action: { /* open dropdown */ }) .ebStyle(.light)
// Applied filter — brand fill, avatar + close EBChip( label = "Filter Name", style = EBChipStyle.Filled, leading = { EBAvatar(initials = "DM") }, trailing = EBChipTrailing.Close, onRemove = { /* remove filter */ } ) // Inactive filter — light, label only EBChip( label = "Category", style = EBChipStyle.Light ) // Dropdown trigger with selected value EBChip( label = "Sort by", selectedValue = "Conservative first", style = EBChipStyle.Light, trailing = EBChipTrailing.Chevron, onClick = { /* open dropdown */ } )
| Requirement | iOS | Android |
|---|---|---|
| Tap target | 32px height is below HIG 44pt — wrap in a 44pt-tall hit area | 32dp height is below Material 48dp — expand touch target via Modifier.minimumInteractiveComponentSize() |
| Role | .accessibilityAddTraits(.isButton) | Use semantics { role = Role.Button } |
| Close button label | .accessibilityLabel("Remove filter: \(label)") | contentDescription = "Remove filter: $label" |
| Dropdown indicator | .accessibilityHint("Double-tap to change") | Announce chevron via role + state |
| Selected state | .accessibilityAddTraits(.isSelected) for style=filled | selected = true in semantics for active filters |
Do
Use style=filled for applied/active filters, style=light for inactive filters and dropdown triggers, style=outline when the surface beneath is already light gray.
Don't
Mix filled and light chips in the same filter row without intent — it signals "one filter is selected," so using both styles for unrelated reasons misleads the user.
Do
Pair the close affordance with applied filters so users can remove them with a single tap.
Don't
Add a close icon to dropdown-trigger chips — the chevron already indicates the tap behavior; a close icon implies removal instead of picking.
Do
Keep the chip label to one or two words. Use selectedValue to show the picked option separately.
Don't
Stretch chips to fill width — they're meant to fit their content. If a control needs full width, use a Button or Select Field instead.
| ID | Criterion | Status | Notes |
|---|---|---|---|
| C1 | Layer Structure & Naming | Ready | Semantic names: container, Placeholder, Close, Chevron Down. |
| C2 | Variant & Property Naming | Requires Rework | Split across two components. with icon uses yes/no. Dropdown uses type="with active time". |
| C3 | Token Coverage | Ready | All colors, radii, spacing, and typography bound to tokens. |
| C4 | Native Mappability | Ready | Maps to custom pill on iOS and FilterChip/InputChip on Android. |
| C5 | Interaction State Coverage | Requires Rework | No pressed / disabled / error states. Selected is implied by style=filled. |
| C6 | Asset & Icon Quality | Requires Rework | Leading slot is a hardcoded 24px gray circle — should be a swappable Avatar/Icon instance. |
| C7 | Code Connect Linkability | Needs Refinement | Blocked by C2 consolidation. |
| Source | Style | Leading | Trailing | Node ID |
|---|---|---|---|---|
| Filter | Filled (primary) | Avatar | Close | 18336:22244 |
| Filter | Filled (primary) | — | — | 18336:22253 |
| Filter | Light | Avatar | Close | 18336:22257 |
| Filter | Light | — | — | 18336:22266 |
| Filter | Outline | Avatar | Close | 18336:22270 |
| Filter | Outline | — | — | 18336:22279 |
| Filter w/ Dropdown | Light | — | Chevron | 18336:22292 |
| Filter w/ Dropdown | Light (w/ selected value) | — | Chevron | 18336:22284 |
type + with icon. Dropdown uses type="with active time". Booleans are yes/no. Should consolidate to style / leading / trailing + optional selectedValue.
Open