A small React + TypeScript app for browsing and selecting projects with search, filters, deep-link routing, and simulated async loading.
- Search projects by title or description with a debounced input
- Filter by project status (
active,paused,archived) - Filter by project tags using multi-select checkboxes
- URL sync for search and filter state using
URLSearchParams - Deep link selection using route-based project detail (
/projects/:projectId) - Project detail overlay with accessible close behavior
- Simulated async load state on first app render
- Error state support with retry button
- Empty state messaging when filters yield no results
- Keyboard accessible list items and form controls
- The search input is debounced by
300ms. - This prevents the UI from filtering on every keystroke and provides a smoother user experience.
- Debounce is implemented in
src/hooks/useDebounce.ts.
- Status filter is rendered as a
<select>control. - Tag filters are rendered as checkbox chips.
- Search, status, and tags combine using AND logic.
- Search, status, and selected tags are stored in the URL query string.
- Refreshing or bookmarking restores the same filter state.
- Project selection is represented by a route:
/projects/:projectId
- This route-based approach keeps the selected detail state explicit and shareable.
- The app simulates an async fetch on initial load using
setTimeout. - While data is loading, a loading message is shown.
- If the fetch fails, an error message is displayed with a retry button.
- Project cards are keyboard-focusable and respond to
Enter/Space. - The app uses semantic headings (
h1,h2) and proper form labels. - The detail overlay is launched from the route and can be closed via the backdrop.
## Run locally
Install dependencies and start the dev server:
```bash
npm install
npm run dev
src/App.tsx— route configurationsrc/components/ProjectHub.tsx— main hub page and detail overlay behaviorsrc/components/ProjectList.tsx— filtered project listsrc/components/ProjectCard.tsx— accessible project item cardssrc/components/SearchInput.tsx— labeled search fieldsrc/components/Filters.tsx— status and tag filterssrc/components/ProjectDetail.tsx— detail overlaysrc/hooks/useDebounce.ts— debounced value hooksrc/data/projects.json— project fixture data
\