Skip to content

Conversation

ilsea
Copy link
Member

@ilsea ilsea commented Oct 9, 2026

Closes #36

What

  • BookCardSkeleton: placeholder in the shape of a BookCard, shown while a list loads
  • LoadingState: screen reader announcement (announceOnly) plus a pulsing dot for pages without a skeleton
  • ErrorState: message and "Try again" button
  • EmptyState: title, message and optional action button
  • BookGrid now renders skeletons via isLoading, and takes a single shelf map instead of savedIds + ratings
  • BrowsePage now uses BookGrid instead of its own grid (this also ensures skeleton and card widths are matching)
  • BookDetailPage handles loading, error and book-not-found
  • Button variants renamed: primary → default, secondary → emphasis

Temporary, to replace when queries are connected

  • Hardcoded isLoading in BrowsePage and BookDetailPage, and isError in BookDetailPage
  • onRetry is a console.log, should be the query's refetch

How to test

  • Visit /book/nonsense to see the empty state
  • Set the temporary flags to true to see loading and error (in a page file)
  • In dev tools, emulate prefers-reduced-motion: reduce and check that the loading state pulse stops

For review

BrowsePage.tsx is touched: it now renders through BookGrid, and its duplicate .grid CSS is removed. Please pull before continuing work on search/filter/sort there.

Screenshots

image image image

ilsea added 6 commits October 9, 2026 09:48
New:
- `BookCardSkeleton.tsx`
- `BookCardSkeleton.module.css`

Modified:
- `BookCard.module.css`: add comment to inform that the skeleton uses and is dependent on that file to keep the format identical between real and skeleton book cards
- `BookGrid.tsx` now handles the actual rendering of skeleton books, takes isLoading as a prop from the page who calls it. The props `savedIds` and `ratings` were replaced by `shelf` to reflect current data shape.
- `BrowsePage.tsx` now uses BookGrid to render results, where before it did this itself using BookCard. TEMPORARY: hardcoded `isLoading` to ensure that BookGrid is called on correctly. Must be swapped for real loading logic.
- `BrowsePage.module.css`: remove .grid rules since this page no longer does this itself.
New:
- `LoadingState.tsx` and `.module.css`: a role="status" wrapper with a visually hidden label, plus one pulsing dot to show loading state. Uses `announceOnly` to allow different visual loading (skeleton book cards) but retain the screen reader message.

Modified:
- `BrowsePage.tsx` updated with the new `<LoadingState announceOnly />`
- `BookDetailPage.tsx` updated with the pulsing dot + label.

Note: Both of these use a temporary, hardcoded "isLoading" that has to be replaced with real loading logic.
primary -> default
secondary -> emphasis

Need these for further work on this branch. Kept bumping into misunderstandings of which one was the filled, brightly colored one, and which one was the quiet, outlined one. Should make more sense now.
New:
- `ErrorState.tsx` and `.module.css`: role="alert" message with a "Try again" button that calls `onRetry`. `headingLevel` (1 | 2) lets it be the page's h1 when it replaces the whole page.
- `EmptyState.tsx` and `.module.css`: title, message and optional `action` button. Same `headingLevel` prop.

Modified:
- `BookDetailPage.tsx`: shows `ErrorState` on a failed query and `EmptyState` ("Book not found", back to browse) when the id doesn't exist. Loading is checked first, then error, then not found, so a loading or failed query is never mistaken for a missing book.

Note: `isError` is a temporary, hardcoded flag, and `onRetry` is a temporary console.log. Both must be replaced with the real query's `error` and `refetch`. "Back to browse" assumes Browse is at `/`.
@ilsea ilsea requested a review from a team as a code owner October 9, 2026 10:21
@ilsea ilsea linked an issue Oct 9, 2026 that may be closed by this pull request
@ronnenga ronnenga merged commit 3f63991 into main Oct 9, 2026
@ronnenga ronnenga deleted the 36-feedback-states branch October 9, 2026 13:54
Sign in to join this conversation on GitHub.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feedback states
2 participants