CitySelector
ImplementedMulti-select city facet (SEARCH-05, ADR-055). All-cities chip clears the selection, toggling the last city off returns to All, and the selection is capped (default 5) with unselected chips disabled at the cap. Router-agnostic and i18n-free: the consumer injects copy, cookie persistence and URL updates. Handles loading, empty and error+retry states.
components/molecules/CitySelector/CitySelector.tsxProps
CitySelector
citiesCityOption[]—Ordered cities ({ slug, label, count? }).
selectedstring[]—Selected slugs; empty means all cities.
onChange(slugs: string[]) => void—Next selection, de-duplicated and capped at max.
allLabelstring—Label of the clearing All-cities chip.
ariaLabelstring"Filter by city"Accessible name of the chip group.
maxnumber5Maximum simultaneous cities.
loadingbooleanfalseRenders the loading status instead of chips.
errorstring | nullnullRenders a role=alert state, with retry when onRetry is provided.
onRetry() => void—Retry action shown with the error state.
loadingLabelstring"Loading cities…"Loading copy.
errorLabelstring"Cities are unavailable"Fallback error copy when error is an empty string.
retryLabelstring"Retry"Retry button copy.
emptyLabelstring"No cities available"Copy when the facet is empty.
limitLabelstring—Status copy announced at the selection cap.
size"sm" | "md""sm"Chip size token.
classNamestring—Utility class passthrough.
<CitySelector />