East Blue
KeepNeeds Refinement
Chip Component link

A pill-shaped selector carrying a label and an optional chosen value, with optional leading and trailing icons and a slot for an attached dropdown.

Keep — all findings resolved
Rebuilt on node 5595:39596 in the 2026 Working File, and every recommendation from the previous assessment has landed. Two overlapping components are consolidated into one 24-variant set — hasValue × State × hasLeadingIcon × hasTrailingIcon — with a property schema following §1, §2 and §5, identical layer naming across all 24 variants on the §3 vocabulary, Pressed and Disabled states with properly muted disabled text, the offset frames and colored _space_* spacers removed, and dropdown group replaced by a real Dropdown-Slot. Scope is confirmed dropdown-only, so Pressed means finger-down rather than doubling as a selection; the leading Placeholder is a deliberate swap target; and the 80% pressed-label opacity is the same intentional treatment confirmed elsewhere in the system. All four DS Health traits pass; the only item still open is Code Connect, blocked until the native library exists.
In Context

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

Vouchers
Live Preview
Filter Name
Properties
style
leading
trailing
DS Health
Reusable
Pass
A generic pill selector — filter row, sort control, dropdown trigger. Nothing ties it to one screen, and the four axes cover the combinations a chip actually appears in.
Self-contained
Pass
Owns its pill chrome, typography and state colors. Dropdown-Slot attaches external content without the chip needing to know what it is.
Consistent
Pass
The schema follows §1, §2 and §5 — hasValue × State × hasLeadingIcon × hasTrailingIcon — and all 24 variants now carry identical layer names on the §3 vocabulary, so each text layer exposes as a single property. The Disabled state mutes its text in line with Counter and Search Field rather than diverging.
Composable
Pass
Dropdown-Slot is a real Figma Slot on the twelve variants that signal a dropdown, ContentRow composes label and value independently, and the leading position takes a swappable instance.
Behavior
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
Issues
  • Consolidated into one component on the Working File. v2.0: Rebuilt on node 5595:39596. What were two overlapping chip components are now a single 24-variant set — hasValue (2) × State (3) × hasLeadingIcon (2) × hasTrailingIcon (2) — with every combination present and no gaps. This is the rename-and-consolidate recommendation applied. (C2 · Family) C2 · Variant & Property Naming
  • Property schema rebuilt on the naming guidelines. v2.0: The old yes/no values and the “with active time” enum are gone. Booleans now use the has prefix with lowerCamelCase per §2 — hasValue, hasLeadingIcon, hasTrailingIcon, the last two replacing the ambiguous hasLeading / hasTrailing — and State is PascalCase per §1 with Title Case values per §5. Every axis now says what it controls. (C2 · Rename) C2 · Variant & Property Naming
  • Pressed and Disabled states added. v2.0: State = Default | Pressed | Disabled replaces the single default state. Pressed fills the pill #005CE5; Disabled fills it #EEF2F9; Default is white with a #D7E0EF border. (C5) C5 · Interaction State Coverage
  • Layer naming rebuilt throughout. v2.0: The two frames named offset and the #label sigil are gone. Every variant now reads Pill → LeadingIcon · ContentRow → Label · Value · TrailingIcon, following the §3 vocabulary. Two layers were missed in the sweep and are tracked below; the rest is done. (C1 · Rename) C1 · Layer Structure & Naming
  • dropdown group is now a real Figma Slot. v2.0: Dropdown-Slot is a genuine SLOT node rather than a frame standing in for one, kebab-case per §4, and it appears on exactly the twelve variants where hasTrailingIcon=True — the chevron is what signals a dropdown, so slot and affordance are consistent by construction. A consumer attaches their own menu without detaching. (C1 · Slot) C1 · Layer Structure & Naming
  • Colored spacer instances removed. v2.0: The _space_4 and _space_8 instances filled #00FF66 and #FFFF00 are gone from the layer tree; spacing is carried by auto-layout. A native implementation now sees the children that actually exist. (C1) C1 · Layer Structure & Naming
  • Rename sweep completed across all 24 variants. v2.1: Verified on the live node. label → Label (5595:39613) and Trailing Icon → TrailingIcon (5595:39661). Every variant now carries identical layer names — Pill → LeadingIcon · ContentRow → Label · Value · TrailingIcon — so Label and Value each expose as a single text property across the whole set rather than fragmenting. (C1 · Rename) C1 · Layer Structure & Naming
  • Disabled state now mutes its text. v2.1: Label drops to #C2CFE5 and Value to #9BC5FD, replacing the full-strength #6780A9 and #005CE5 that made a disabled chip read as an available action. The muted blue on the value is a nice touch — it keeps the label/value hierarchy legible while removing the affordance, rather than flattening both to one grey. Consistent with Counter and Search Field, which both mute to #C2CFE5. (C5 · Token) C5 · Interaction State Coverage
  • Scope confirmed dropdown-only — no selected state needed. v2.2: Chip is a dropdown trigger, not a filter toggle. hasValue=True is what a made choice looks like, and Dropdown-Slot on the twelve hasTrailingIcon=True variants is what the component exists to attach. Pressed therefore means what it says — a transient finger-down state released on lift — and does not double as a persistent selection. Recorded so the absence of isSelected reads as scope rather than an omission: a screen needing an on/off filter pill reaches for a different component rather than pressing this one into service. (C5 · State) C5 · Interaction State Coverage
  • Leading Placeholder confirmed a deliberate swap target. v2.2: The 24×24 Placeholder in each LeadingIcon frame is the intended instance-swap point for consumer content — the same pattern Detail Hero uses. The asymmetry with the trailing side is intentional rather than an oversight: the trailing position is a fixed Chevron Down plus a named Dropdown-Slot, because what attaches there is a menu the chip must anchor, while the leading position takes an arbitrary icon the chip only has to reserve room for. Two different jobs, two different mechanisms. Attested rather than verified — instance-swap property definitions are not readable through the review tooling. (C6 · Composition) C6 · Asset & Icon Quality
  • Pressed label opacity confirmed intentional. v2.2: Label at #F6F9FD 80% against the solid #005CE5 pill is deliberate — it holds the label back so the chosen Value reads as the brighter of the two while the chip is held down, preserving the same hierarchy the Default state gets from #6780A9 against #005CE5. Consistent with the treatment already confirmed on Page Banner and Detail Hero, and covered by the same owner decision: the composited values are token-bound rather than local overrides. Attested rather than verified — opacity token bindings are not readable through the review tooling. (C3 · Token) C3 · Token Coverage
Styles
Filled
Filter Name
Properties
Style
Leading
Trailing
Properties
Style Filled
Leading avatar
Trailing close
Colors
Background #005CE5
Label #FFFFFF
Icon #F6F9FDB8
Typography
Text style Primary/Label/Base
Layout
Height 32px
Radius 99px (pill)
Padding L 4px
Padding R 14px
Leading avatar 24 × 24
Close icon 16 × 16
Colors by Style

Three style modes, each with bg, label, and icon tokens. Dropdown adds label-link and chevron.

Role Element 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
Category
Properties
Style
Leading
Trailing
Properties
Style Light
Leading none
Trailing none
Colors
Background #EEF2F9
Label #6780A9
Icon #7E96BE
Typography
Text style Primary/Label/Base
Layout
Height 32px
Radius 99px (pill)
Padding horizontal 14px
Outline
Category
Properties
Style
Leading
Trailing
Properties
Style Outline
Leading none
Trailing none
Colors
Background #FFFFFF
Border #D7E0EF
Label #6780A9
Typography
Text style Primary/Label/Base
Layout
Height 32px
Radius 99px (pill)
Border 2px
Padding horizontal 14px
Dropdown
Sort byConservative first
Properties
Style
Leading
Trailing
Properties
Style Light
Leading none
Trailing chevron
Colors
Background #EEF2F9
Label #6780A9
Selected value #005CE5
Chevron #005CE5
Typography
Text style Primary/Label/Base
Layout
Height 32px
Radius 99px (pill)
Padding left 16px
Padding right 12px
Chevron size 24 × 24
Installation Planned API

iOS — Swift Package Manager

.package(url: "https://github.com/AY-Org/eb-ds-ios", from: "1.0.0")

Android — Gradle (Kotlin DSL)

implementation("com.eastblue.ds:chip:1.0.0")

Import

import EastBlueDS
import com.eastblue.ds.chip.*
Property Mapping
Figma PropertySwiftUICompose
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
SwiftUI
ios/Components/Chip/EBChip.swift
Jetpack Compose
android/components/chip/EBChip.kt
Usage Snippets Planned API
Usage
// 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 */ }
)
Accessibility
RequirementiOSAndroid
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
Usage Guidelines

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.

Criteria Scorecard
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.
Variants Inventory (0 total)

SourceStyleLeadingTrailingNode ID
FilterFilled (primary)AvatarClose18336:22244
FilterFilled (primary)——18336:22253
FilterLightAvatarClose18336:22257
FilterLight——18336:22266
FilterOutlineAvatarClose18336:22270
FilterOutline——18336:22279
Filter w/ DropdownLight—Chevron18336:22292
Filter w/ DropdownLight (w/ selected value)—Chevron18336:22284
1.0.1 — September 2026Patch
Documentation backfill · node 5595:39596
Resolved issues recorded. 11 resolved issues on the Overview tab had no changelog row: Consolidated into one component on the Working File; Property schema rebuilt on the naming guidelines; Pressed and Disabled states added; Layer naming rebuilt throughout; dropdown group is now a real Figma Slot; Colored spacer instances removed; Rename sweep completed across all 24 variants; Disabled state now mutes its text; Scope confirmed dropdown-only — no selected state needed; Leading Placeholder confirmed a deliberate swap target; Pressed label opacity confirmed intentional.
Docs
1.0.0 — April 2026Major
Initial Assessment · nodes 18336:22243 + 18336:22283
Assessed as Chip — Two Figma components ("Filter" with 6 variants, "Filter with Dropdown" with 2 variants) share the same pill anatomy. Recommended rename + consolidation into a single Chip component with semantic slot props. Documented
Initial
Two-component split, mismatched schemas — Filter uses type + with icon. Dropdown uses type="with active time". Booleans are yes/no. Should consolidate to style / leading / trailing + optional selectedValue. Open
C2 Open
No pressed/disabled/error states — Engineers must improvise these affordances. Open
C5 Open
Leading slot is hardcoded placeholder — 24px gray circle instead of a swappable Avatar/Icon instance. Open
C6 Open
Code Connect mappings — Blocked by C2 rename + consolidation. Open
C7 Open