Chips

mandatory

Compact element representing an entity, attribute, or action — smaller than a button and used in groups. Material parity (`/components/chips`). Covers four canonical variants (assist, filter, input, suggestion) and their behaviors.

Spec — Chips

Facet *isual*of Koder Design. Material parity: https://m3.material.io/components/chips.

4 variants

Variant Purpose Selectable Removable
*ssist* Trigger contextual action tied to a noun ("Add to calendar") No No
*ilter* Toggle inclusion in a filtered set Yes (multi-select) No
*nput* Represent user-entered value (email tag, applied filter) No Yes (× button)
*uggestion* Predefined response or query option One-shot tap No

Pick variant by question: "Does this represent a thing I typed?" → input. "Does this filter a list?" → filter. "Does this give me a shortcut to type something?" → suggestion. "Does this trigger an action attached to nearby content?" → assist.

Anatomy

   ┌──────────────────┐       ┌──────────────────┐
   │  ⚙   Settings    │       │   ●  Important × │
   └──────────────────┘       └──────────────────┘
       ↑     ↑                    ↑      ↑      ↑
     icon  label              leading  label  remove
                              (optional)     (input only)
  • *eight* 32 px (default)
  • *adding* 12 px horizontal (label only) / 8 px (with icon)
  • *orner radius* 8 px (Material 3 default, see preset variation)
  • *abel* label-large (14/20, weight 500)
  • *eading icon* 18 px, optional
  • *railing* × icon (input variant) or check (selected filter)
  • *it target* minimum 48 × 48 px (extends invisibly around chip)
  • *ontainer bg* variant-specific (see R2)

R1 — Group layout

Chips appear in groups. Layout rules:

Layout When
*orizontal scroll* Mobile / narrow surface, many chips
*rap* Default — chips wrap to next line when overflow
*ingle row* Few chips (≤ 5) that always fit

Spacing between chips: * px horizontal, 8 px vertical*

R2 — Visual by variant + state

Variant Rest bg Rest border Selected bg Selected border
Assist transparent 1 px outline n/a n/a
Filter (unselected) transparent 1 px outline secondary-container none
Filter (selected) secondary-container none (same) none
Input surface-container-low 1 px outline-variant n/a n/a
Suggestion transparent 1 px outline (one-shot tap, no selected state) n/a

Elevation: 0 dp at rest; rises to 2 dp on hover (Material 3 "elevated" chip is an opt-in variant — document explicitly if used).

R3 — Filter chip selection

Action Result
Tap unselected Becomes selected (add filter)
Tap selected Becomes unselected (remove filter)
Long-press (touch) Show tooltip with full label

Filter chips are *ulti-select*by default — multiple can be selected simultaneously. If single-select needed (mutually exclusive), use radio buttons or segmented buttons instead.

Selection state shows:

  • Leading check icon (✓) replaces optional leading icon
  • Background fills with secondary-container
  • Border removed (filled state)

R4 — Input chip removal

× icon on right side, 18 px, accessible via:

  • Tap × → remove chip + announce "Removed: [label]" to screen reader
  • Backspace when chip has keyboard focus → remove
  • Backspace in adjacent text field → focus last chip
  • Keyboard delete on focused chip → remove + move focus to previous

Animation: chip fadeout (motionfast) + adjacent chips slide to fill.

R5 — States (all variants)

State Visual change
Rest Base style
Hover State layer 8% over base
Focused 2 px focus ring outside chip border
Pressed State layer 12%
Disabled 38% opacity, no interaction

R6 — With icon

Leading icon slot accepts:

  • 18 px icon (default — matches text height)
  • 24 px avatar (input chip representing a person)

When icon is present:

  • Padding-left reduces from 12 px → 8 px
  • Icontolabel gap: 4 px

Selected filter chip ALWAYS shows check leading; replaces optional icon (don't try to show both — order is check OR icon).

R7 — Accessibility

  • Assist: role="button" + accessible name from label
  • Filter: role="checkbox" (multi) OR role="radio" (single, rare)

    with aria-checked state

  • Input: role="button" for chip + nested role="button" for ×

    remove; remove button has aria-label="Remove [label]"

  • Suggestion: role="button"
  • Group container: role="group" + aria-label describing the

    collection

  • Keyboard:
    • Tab: enters first chip in group, then Tab moves OUT
    • Arrow Left/Right: moves between chips within group
    • Space / Enter: toggles (filter) or activates (assist /

      suggestion)

    • Backspace / Delete: removes (input)

R8 — Density

Density Height Padding Icon size
Compact 28 px 10 px 16 px
Default 32 px 12 px 18 px
Comfortable 40 px 16 px 20 px

Inherits from customization.kmd.

R9 — Per-preset variation

Preset Corners Selected style
material3 8 px radius Filled tonal container
material2 16 px pill Saturated accent, white text
ios_cupertino 16 px pill Filled accent
gnome 6 px radius Solid accent border, tonal bg
windows_11 4 px radius Accent color filled, subtle outline
brutalist 0 px (sharp) Inverted colors, 2 px border
terminal_classic Bracketed text [Filter] / [X] Asterisk prefix *[Filter]

R10 — Forbidden patterns

  • ❌ Chips taller than 48 px (becomes a button; use button instead)
  • ❌ Chips with multi-line labels (truncate or use card / list)
  • ❌ Mixing variants in a single group (a row of filter chips with

    one input chip in the middle is confusing)

  • ❌ Filter chip groups acting as single-select (use radio / segmented

    buttons)

  • ❌ Chip without label (icon-only — use icon button)
  • ❌ Long-press as the only way to remove an input chip (no

    discoverability)

  • ❌ Animating bg color on selection without a state layer (jarring

    flash)

  • ❌ Hit target < 48 × 48 px
  • interaction/selection.kmd — multi-select pattern
  • interaction/states.kmd — hover / pressed / focused layers
  • themes/color-roles.kmdsecondary-container for selected filter
  • themes/typography.kmdlabel-large
  • components/buttons.kmd — single primary action sibling
  • components/text-fields.kmd — input chip parent context
  • foundations/elements.kmd — Control + Marker families

Source: ../home/koder/dev/koder/meta/docs/stack/specs/components/chips.kmd