# Accessible Multi-Select

## Objective

Let people pick many items and always know exactly what they have picked.

A multi-select whose selection state is visible, removable, and announced — chips, counts, select-all, and a keyboard model that works.

## Before You Begin

This feature is being added to an application that already exists and already
works. Do not scaffold a new project, and do not assume a blank slate.

Inspect the codebase first and establish:

- The existing application structure and where code of this kind already lives.
- The framework and version in use.
- The existing design system — colours, spacing, typography, and component conventions.
- Existing UI components you can reuse instead of writing new ones.
- The existing database structure, if this feature needs to persist anything.
- The existing authentication and authorization system, if this feature is user-scoped.
- Dependencies already installed, so you don't add a library that duplicates one.
- The existing test setup and conventions.

Only start writing code once you understand the above. If the application
already implements part of this feature, extend it rather than replacing it.

## Implementation Instructions

1. Render each selection as a removable chip with an accessible label naming the item, not a bare X.
2. Define one keyboard model and stick to it: arrows move through options, Space or Enter toggles, Backspace on an empty input removes the last chip, Escape closes the list without discarding selections.
3. Announce the selection count on every change through a polite live region, and announce removals by name.
4. If the app already has a typeahead or suggestion component, extend it rather than building a second one. This feature is about selection state, not about searching.
5. Do NOT let bulk removal happen without recourse. Select-all and clear-all must state how many items they affect and be undoable.

## UI and UX Requirements

Match the application's existing design system exactly. Reuse its components,
spacing, and typography. This feature should look like it was always there.

## Responsive Requirements

Works on mobile, tablet, and desktop. Touch targets are large enough to hit on a
phone, and nothing overflows horizontally at 320px.

## Accessibility Requirements

- Fully keyboard navigable.
- Correct semantic elements and ARIA roles.
- Visible focus states.
- Meets WCAG AA contrast.
- Dynamic changes are announced to screen readers.
- Respects prefers-reduced-motion.

## Edge Cases

- Selected items that fall outside the current search results must stay selected and stay visible.
- The same item must never be selectable twice, including via paste or programmatic set.
- Select-all must mean all matching the current filter, and must say so — not all options in existence.
- A large selection must collapse to a count with a way to expand, so the chip pile does not swallow the page.
- Removing a chip must move focus to a predictable neighbour, never to the body.
- Chips must wrap and remain tappable at 320px, with touch targets large enough to hit.
- A maximum selection limit must be announced before it is hit, not enforced by a silent no-op.

## Testing

Exercise the feature end to end in the running application. Cover every edge case
above, then run the existing test suite and confirm nothing regressed.

## Acceptance Criteria

- [ ] Every selection is visible as a labelled, removable chip.
- [ ] The whole control is operable by keyboard alone, with a documented key map.
- [ ] Selection count and individual removals are announced to screen readers.
- [ ] Selected items survive searching and filtering the option list.
- [ ] Duplicate selections are impossible.
- [ ] Select-all and clear-all state their scope and can be undone.
- [ ] The feature matches the existing design system.
- [ ] No existing functionality is broken.

## Adaptation Rules

- Match the existing design system. Do not introduce a new colour palette,
  spacing scale, or component library.
- Reuse existing components and utilities wherever they fit.
- Follow the naming, file layout, and code style already present.
- Do not upgrade, replace, or remove existing dependencies to make this
  feature fit. Adapt the feature to the app, not the app to the feature.
- Do not break existing functionality. If a change is genuinely required in
  existing code, make the smallest one that works and say so.
- If something in these instructions conflicts with how the application is
  built, follow the application and explain the deviation.

## Final Verification

Before you report the work as done:

1. Re-read the acceptance criteria above and check each one against what you
   actually built.
2. Run the application and exercise the feature end to end.
3. Run the existing test suite and confirm you have broken nothing.
4. Check the feature on mobile, tablet, and desktop widths.
5. Check keyboard navigation and focus handling.
6. Summarize what changed: files added, files modified, and anything you
   deliberately did differently because of how this application is built.

If any acceptance criterion is unmet, fix it before reporting completion.
