CodeForPhilly / CodeForPhilly/codeforphilly-ng
Extract a shared combobox hook for SearchBox and TagPicker
- Dominant language
- TypeScript
- Stars
- 1
- Forks
- 1
- Avg merge
- 5d 3h
- Merged PRs (30d)
- 9
Description
Follow-up from PR #155 (ARIA correctness).
`SearchBox` and `TagPicker` now both implement the ARIA APG combobox-with-listbox pattern by hand: `open` / `activeIndex` state, clamped `activeIdx`, `useId()`-derived listbox/option ids, `aria-activedescendant`, wrapping ArrowUp/ArrowDown, Enter/Escape, guarded `onMouseMove` highlight, and close-on-focus-out. The two copies have already drifted in small ways (SearchBox swallows mousedown on the popup and closes on input blur; TagPicker uses a container `onBlur` + `relatedTarget` check with `tabIndex={-1}` options).
Extract a `useCombobox` hook (or adopt shadcn's `Command`) so the keyboard/ARIA contract lives in one place and the two widgets only differ in how they render options and what activation does. Keep the existing `SearchBox.test.tsx` / `TagPicker.test.tsx` as the behavioural contract.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01RdRwHvDupRLV8GuJpYKzEr
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by locating SearchBox and TagPicker, then compare their existing combobox state, ARIA IDs, keyboard handlers, and focus-out behavior. Use SearchBox.test.tsx and TagPicker.test.tsx as the behavioral contract; done means the shared hook or adopted Command approach centralizes the contract without changing either widget's rendering and activation behavior, and both test suites pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- accessibility, frontend, testing
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100