# Filter Chip

Level: molecule.

## Purpose and use

Summarize one filter and expose its controlled picker and lifecycle action.
Use Chip inside a Filter Row or a filter-dropdown wrapper; it never owns the
overlay or applied data.

## Current local anatomy, behavior, and accessibility

- The main native button contains label, optional applied value/count and a
  chevron. A trailing action appears for every optional filter and for a filled
  required or pinned filter.
- `filled` exposes a value or, with `multiple`, a count. Finite numeric counts
  above 99 display as `99+`. The label colon appears only when filled content is
  displayed; opened state alone does not add it.
- The trigger emits `openRequest` with the inverse of controlled `opened`; it
  holds no local open state. The parent owns the overlay and returns `opened`.
  The trailing action stops propagation and emits `clear` for `required`,
  `reset` for `pinned`, or `remove` for `optional`; it never changes filter data.
- `aria-expanded` follows `opened`, and the trigger name includes its value or
  count. Invalid state adds `aria-invalid`, an accessible error description,
  and an error Tooltip on hover/focus; `errorText` defaults to
  «Выберите значение». Disabled blocks both actions and takes visual precedence.
- Supply a filter noun as label and a recognizable applied value. Screens own
  clearing, restoring defaults, removing optional filters, and focus/overlay
  coordination.

## Visual states and tokens

The exact Figma Chip gallery is verified at node `14713:33911`; its behavior
specification is verified at `12367:83559`.

- A Chip is 32px high, max 440px wide, uses `--radius-s`, and has an 8px outer
  gap, `--space-300` inline-start padding, `--space-200` block/inline-end
  padding, and `--space-50` between label, value/count, and chevron. Label text
  uses `--typography-description-puma`; a value uses
  `--typography-description-accent-lion`.
- The Figma gallery exposes `Clear` and `Selected` (`None`, `1`, and `Many`)
  variants with `Default`, `Hover-remove`, `Hover-edit`, `Active`, `Disabled`,
  `Error`, and `Error-hover` state previews. The local `opened` contract maps
  to the Figma `Active` preview only with displayed applied value/count; an
  opened empty Chip retains the neutral `Default` treatment. Lifecycle, rather
  than a generic removable flag, determines the trailing action. `required`
  clears, `pinned` resets, and `optional` removes.
- Use semantic tokens rather than raw colors: neutral/default
  `--color-background-level-2` (including an opened Chip without applied
  content); accent selected/open treatment with applied value/count uses
  `--color-background-accent-secondary`, its hover/pressed counterparts,
  `--color-background-dropdown-active`, red error backgrounds
  `--color-content-background-red` / `--color-content-background-red-hover`,
  primary/secondary/tertiary text-icon tokens, and
  `--color-text-icon-black-contrast` for foreground contrast over red error
  backgrounds. Retain danger semantics for the error stroke
  (`--color-stroke-danger`) and action.

## Local component contract

This is the active owned contract for `component.filter-chip`. The API below
is verified against the current local implementation, focused test and story.
The Source commit `0112cba0779a2d2a4b6c7a17243201694344d70a` remains
migration provenance, not the runtime owner.

### Classes and selectors

- `WblFilterChipComponent` — `wbl-filter-chip` (src/app/design-system/patterns/filter-chip/filter-chip.component.ts).

### Inputs

- `WblFilterChipComponent.label = input('Label')`
- `WblFilterChipComponent.value = input('Value')`
- `WblFilterChipComponent.filled = input(false)`
- `WblFilterChipComponent.multiple = input(false)`
- `WblFilterChipComponent.count = input<string | number>(2)`
- `WblFilterChipComponent.lifecycle = input<WblFilterLifecycle>('pinned')`
- `WblFilterChipComponent.opened = input(false)`
- `WblFilterChipComponent.invalid = input(false)`
- `WblFilterChipComponent.errorText = input('')`
- `WblFilterChipComponent.disabled = input(false)`

### Public types and allowed values

```ts
type WblFilterLifecycle = 'required' | 'pinned' | 'optional';
type WblFilterAction = 'clear' | 'reset' | 'remove';
```

### Models

- None.

### Outputs

- `WblFilterChipComponent.openRequest = output<boolean>()`
- `WblFilterChipComponent.action = output<WblFilterAction>()`

### Slots and projection markers

- The exact template has no Angular content-projection slot.

### Local evidence

- Code: `src/app/design-system/patterns/filter-chip/filter-chip.component.ts`.
- Focused test: `src/app/design-system/patterns/filter-chip/filter-chip.component.spec.ts`.
- Public export: `export * from './patterns/filter-chip/filter-chip.component';` in `src/app/design-system/index.ts`.
- Storybook: `storybook/stories/filter-chip.stories.ts` (`Design System/Patterns/wbl-filter-chip`).

## Figma status

The inventory-linked [Figma assembly sidecar](wbl-filter-chip.figma.md) records
the verified local Chip composition and its direct reusable anatomy. The current
read did not expose a Figma main component key, so the sidecar correctly records
no published key; that gap does not prevent the sidecar or Filter Row dependency.

## Provenance

The archived source-document copy is historical evidence only. The active
resolver is local code/test/export and the exact Storybook story above.

## M-002 refinement

The label colon represents displayed applied content, not open state. An opened
chip with no value/count renders only its label; a filled chip with a visible
value or count retains the colon. Accessible naming follows the same content and
must not announce punctuation as if an applied value were present.
