Skip to content

feat(ncids): Implement Autocomplete combobox component#73

Draft
Copilot wants to merge 1 commit into
developfrom
copilot/epic-2-implement-autocomplete-component
Draft

feat(ncids): Implement Autocomplete combobox component#73
Copilot wants to merge 1 commit into
developfrom
copilot/epic-2-implement-autocomplete-component

Conversation

Copy link
Copy Markdown

Copilot AI commented May 13, 2026

Adds a fully accessible, generic Autocomplete combobox component per the WAI-ARIA APG combobox pattern, supporting both sync and async data sources.

Component API

// Sync options
<Autocomplete id="fruit" label="Fruit" options={fruits} onChange={setValue} />

// Async with debounce
<Autocomplete
  id="fruit"
  label="Fruit"
  loadOptions={(q) => fetchFruits(q)}
  debounceDelay={300}
  onChange={setValue}
/>

// Generic option shape
<Autocomplete<Country>
  id="country"
  label="Country"
  options={countries}
  getOptionLabel={(c) => c.name}
  getOptionValue={(c) => c.code}
  onChange={setValue}
/>

Key props (AutocompleteProps<T>)

Prop Default Description
options Synchronous option list
loadOptions Async loader; takes precedence over options
debounceDelay 300 ms before invoking loadOptions
renderOption Custom option renderer (option, isHighlighted) => ReactNode
getOptionLabel / getOptionValue option.label / option.value Adapters for non-standard option shapes
noOptionsMessage "No results found." Empty-state text
loadingMessage "Loading…" Loading-state text
value Controlled selected value

Accessibility

  • Full ARIA combobox pattern: role="combobox", aria-expanded, aria-haspopup="listbox", aria-controls, aria-activedescendant, aria-labelledby
  • Listbox always in DOM (toggled via hidden) so aria-controls always resolves
  • Keyboard: ↑/↓ highlight, ArrowUp from first item clears highlight, Enter selects, Escape closes, Tab closes

Files

  • Autocomplete.tsx — component + exported AutocompleteProps<T> / AutocompleteOption
  • Autocomplete.module.scss — USWDS-aligned CSS module
  • Autocomplete.test.tsx — 25+ unit tests + vitest-axe a11y tests (open and closed states)
  • Autocomplete.stories.tsx — 6 Storybook stories (sync, async, custom renderer, custom shape, disabled, controlled)
  • Autocomplete/index.ts + ncids/index.ts updated barrel exports

Copilot AI linked an issue May 13, 2026 that may be closed by this pull request
16 tasks
Copilot AI changed the title [WIP] Add autocomplete component with async data loading and keyboard navigation feat(ncids): Implement Autocomplete combobox component May 13, 2026
Copilot AI requested a review from adriancofie May 13, 2026 15:15
belaolsonNIH added a commit that referenced this pull request May 14, 2026
* Adjusts Autocomplete.module.scss styling
* Adjusts Autocomplete.test to pass lint tests

Closes #73
@github-actions
Copy link
Copy Markdown
Contributor

Storybook Preview

This PR includes component changes. A Storybook build was verified successfully.

Once merged, the updated Storybook will be deployed to GitHub Pages automatically.

belaolsonNIH added a commit that referenced this pull request May 20, 2026
* Updates Autocomplete.tsx to use MouseEvent instead of PointerEvent
* Adjusts Autocomplete.module.scss styling
* Adjusts Autocomplete.test to pass lint tests

Closes #73
@belaolsonNIH belaolsonNIH force-pushed the copilot/epic-2-implement-autocomplete-component branch from 079c962 to c65870e Compare May 20, 2026 20:54
belaolsonNIH added a commit that referenced this pull request May 20, 2026
* Adds styles.d.ts for Autocomplete.scs file
* Updates Autocomplete.tsx to use MouseEvent instead of PointerEvent
* Adjusts Autocomplete.module.scss styling
* Adjusts Autocomplete.test to pass lint tests

Closes #73
@belaolsonNIH belaolsonNIH force-pushed the copilot/epic-2-implement-autocomplete-component branch from c65870e to 2b271d7 Compare May 20, 2026 21:00
- Implement ARIA combobox pattern (role, aria-expanded, aria-controls,
  aria-activedescendant, aria-haspopup, aria-labelledby)
- Add synchronous options filtering via `options` prop
- Add async data loading via `loadOptions` prop
- Add debounced input (configurable via `debounceDelay`)
- Add custom option rendering via `renderOption` prop
- Add custom label/value extraction via `getOptionLabel`/`getOptionValue`
- Add keyboard navigation (ArrowUp/Down, Enter, Escape, Tab)
- Add clear button (hidden when disabled or empty)
- Add loading state indicator
- Add configurable no-results message
- Add Autocomplete.module.scss CSS module styling
- Add comprehensive unit tests with 90%+ coverage
- Add jest-axe accessibility test
- Add Storybook stories with 6 story variants
- Export from ncids/index.ts barrel
- Use useCallback for resolveLabel/resolveValue to fix deps array
- Add resolveLabel to controlled value sync effect deps
- Change activedescendant → activeDescendant (camelCase)
- Remove redundant named export (use export function declaration)
- Extract stateful Storybook stories into proper components
- Fix ArrowUp: allow de-highlighting from index 0 (→ -1)
- Use literal ellipsis character instead of unicode escape
- Add test for ArrowUp clearing highlight at first item
* Adds styles.d.ts for Autocomplete.scs file
* Updates Autocomplete.tsx to use MouseEvent instead of PointerEvent
* Adjusts Autocomplete.module.scss styling
* Adjusts Autocomplete.test to pass lint tests

Closes #21

Initial plan

chore: initial plan for Autocomplete component

Agent-Logs-Url: https://github.com/NCIOCPL/react-app-shared/sessions/20befcde-a76b-49a2-8a61-fe0075b5fcc5

Co-authored-by: adriancofie <38888889+adriancofie@users.noreply.github.com>

feat: implement Autocomplete combobox component

- Add Autocomplete.tsx with generic TypeScript interface
- Implement ARIA combobox pattern (role, aria-expanded, aria-controls,
  aria-activedescendant, aria-haspopup, aria-labelledby)
- Add synchronous options filtering via `options` prop
- Add async data loading via `loadOptions` prop
- Add debounced input (configurable via `debounceDelay`)
- Add custom option rendering via `renderOption` prop
- Add custom label/value extraction via `getOptionLabel`/`getOptionValue`
- Add keyboard navigation (ArrowUp/Down, Enter, Escape, Tab)
- Add clear button (hidden when disabled or empty)
- Add loading state indicator
- Add configurable no-results message
- Add Autocomplete.module.scss CSS module styling
- Add comprehensive unit tests with 90%+ coverage
- Add jest-axe accessibility test
- Add Storybook stories with 6 story variants
- Export from ncids/index.ts barrel

Agent-Logs-Url: https://github.com/NCIOCPL/react-app-shared/sessions/20befcde-a76b-49a2-8a61-fe0075b5fcc5

Co-authored-by: adriancofie <38888889+adriancofie@users.noreply.github.com>

refactor: address code review feedback for Autocomplete component

- Use useCallback for resolveLabel/resolveValue to fix deps array
- Add resolveLabel to controlled value sync effect deps
- Change activedescendant → activeDescendant (camelCase)
- Remove redundant named export (use export function declaration)
- Extract stateful Storybook stories into proper components
- Fix ArrowUp: allow de-highlighting from index 0 (→ -1)
- Use literal ellipsis character instead of unicode escape
- Add test for ArrowUp clearing highlight at first item

Agent-Logs-Url: https://github.com/NCIOCPL/react-app-shared/sessions/20befcde-a76b-49a2-8a61-fe0075b5fcc5

Co-authored-by: adriancofie <38888889+adriancofie@users.noreply.github.com>

fix: remove redundant optional chaining after bounds check in Autocomplete

Agent-Logs-Url: https://github.com/NCIOCPL/react-app-shared/sessions/20befcde-a76b-49a2-8a61-fe0075b5fcc5

Co-authored-by: adriancofie <38888889+adriancofie@users.noreply.github.com>

(#73) Implement Autocomplete component

* Adds styles.d.ts for Autocomplete.scs file
* Updates Autocomplete.tsx to use MouseEvent instead of PointerEvent
* Adjusts Autocomplete.module.scss styling
* Adjusts Autocomplete.test to pass lint tests

Closes #73
@belaolsonNIH belaolsonNIH force-pushed the copilot/epic-2-implement-autocomplete-component branch from 2b271d7 to a362992 Compare May 20, 2026 21:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[2.3] Story: Implement Autocomplete Component

2 participants