Concept
Netflix shows a grid of title cards. Hovering or clicking a card reveals an inline expanded panel below the card row — a larger hero image, playback controls, genre tags, and a description — without navigating away. A styled ⌄ chevron button in the bottom-right of the expanded panel collapses it back.
Reference screenshot (Netflix, searched "lord of the rings"):
User-attached screenshot shows: normal thumbnail cards in a grid; one card (The Green Knight) is expanded — it floats taller and wider, breaking out of the grid row, with a still image, ▶ / + / 👍 action buttons, a ⌄ collapse chevron, rating badge (R), runtime (2h 16m), quality (HD), and descriptive tags "Violent • Epic • Visually Striking".
Proposed behaviour for Open Library
Where it applies
Both surfaces currently show book cards:
| Surface |
Component |
Card element |
| Autocomplete panel (droppable) |
ol-search-bar — _renderResults() |
.ac-row |
| Full search results page |
ol-search-page → ol-book-card |
<ol-book-card> |
The feature is most impactful on ol-book-card (full results page) since those cards are already larger. The autocomplete rows are space-constrained and may only need a lighter treatment (see open questions).
Interaction model
- Each card has a small ⌄ expand chevron button in its bottom-right corner (visible on hover, always visible on touch).
- Clicking the chevron expands that card in place — the card grows vertically to reveal additional content; surrounding cards reflow below it.
- Only one card is expanded at a time; expanding another collapses the current one.
- The same chevron (now ⌃) collapses back to the compact view.
- Keyboard:
Enter/Space on the chevron toggles; Escape collapses.
Expanded content to show
Fields already available on the work object returned by the OL search API:
- Larger cover image (use
-L size suffix instead of -M)
- First sentence / description (
w.first_sentence or w.description — may need an additional /works/OLxxxW.json fetch if not in search results)
- Subjects (
w.subject — first 4–5 tags)
- Series (
w.series?.[0])
- Edition count (
w.edition_count)
- OL work page link (full
/works/OLxxxW URL)
- Action buttons: "Read now" (if
ebook_access >= borrowable), "Want to Read" / reading-log CTA, "More details →"
What may require an extra fetch
The OL search API does not return description or first_sentence for works. A lightweight fetch to /works/OLxxxW.json on expand (not on card render) could populate these. The fetch should be:
- Triggered only on first expand (cache the result on the element)
- Abortable if the card is collapsed before the response arrives
- Shown as a skeleton/spinner state while loading
Open questions
- Autocomplete rows — should
.ac-row in the droppable panel also get an expand chevron, or is the panel too space-constrained? A simpler option: clicking the row body navigates to the work page; the chevron is omitted in the panel.
- Extra fetch — is
first_sentence / description worth the extra round-trip? Could use subjects + edition count as the expanded content without any additional request.
- Animation — smooth height transition (
max-height CSS transition) vs. instant reflow. CSS transition is preferred for perceived quality but must not janky-scroll on mobile.
- Grid vs. list layout —
ol-search-page currently renders cards in a single column (flex-direction: column). The Netflix effect (card expands across multiple columns) requires a CSS grid layout. Is a grid refactor in scope here, or should the expand just grow vertically in the single column?
Implementation sketch
ol-book-card changes
- Add
_expanded = false reactive state property
- Add chevron button (
▾ / ▴) wired to _toggleExpand()
- In
_toggleExpand(): fire a custom ol-card-expand event (bubbles, composed) so the parent page can collapse any previously open card
- Render expanded content block conditionally; trigger fetch on first expand
ol-search-page changes
- Listen for
ol-card-expand and set _expandedWork to the work key; re-render (Lit handles diffing)
- Pass
.expanded=${w.key === this._expandedWork} to each <ol-book-card>
Pure-logic additions (filters.js or new utils/works.js)
buildWorkUrl(work) — already exists as bestEdition; may need a workPageUrl variant
isReadable(work) — check ebook_access >= borrowable (already used in bestEdition)
Acceptance criteria
Concept
Netflix shows a grid of title cards. Hovering or clicking a card reveals an inline expanded panel below the card row — a larger hero image, playback controls, genre tags, and a description — without navigating away. A styled ⌄ chevron button in the bottom-right of the expanded panel collapses it back.
Reference screenshot (Netflix, searched "lord of the rings"):
Proposed behaviour for Open Library
Where it applies
Both surfaces currently show book cards:
ol-search-bar—_renderResults().ac-rowol-search-page→ol-book-card<ol-book-card>The feature is most impactful on
ol-book-card(full results page) since those cards are already larger. The autocomplete rows are space-constrained and may only need a lighter treatment (see open questions).Interaction model
Enter/Spaceon the chevron toggles;Escapecollapses.Expanded content to show
Fields already available on the
workobject returned by the OL search API:-Lsize suffix instead of-M)w.first_sentenceorw.description— may need an additional/works/OLxxxW.jsonfetch if not in search results)w.subject— first 4–5 tags)w.series?.[0])w.edition_count)/works/OLxxxWURL)ebook_access >= borrowable), "Want to Read" / reading-log CTA, "More details →"What may require an extra fetch
The OL search API does not return
descriptionorfirst_sentencefor works. A lightweight fetch to/works/OLxxxW.jsonon expand (not on card render) could populate these. The fetch should be:Open questions
.ac-rowin the droppable panel also get an expand chevron, or is the panel too space-constrained? A simpler option: clicking the row body navigates to the work page; the chevron is omitted in the panel.first_sentence/descriptionworth the extra round-trip? Could use subjects + edition count as the expanded content without any additional request.max-heightCSS transition) vs. instant reflow. CSS transition is preferred for perceived quality but must not janky-scroll on mobile.ol-search-pagecurrently renders cards in a single column (flex-direction: column). The Netflix effect (card expands across multiple columns) requires a CSS grid layout. Is a grid refactor in scope here, or should the expand just grow vertically in the single column?Implementation sketch
ol-book-cardchanges_expanded = falsereactive state property▾/▴) wired to_toggleExpand()_toggleExpand(): fire a customol-card-expandevent (bubbles, composed) so the parent page can collapse any previously open cardol-search-pagechangesol-card-expandand set_expandedWorkto the work key; re-render (Lit handles diffing).expanded=${w.key === this._expandedWork}to each<ol-book-card>Pure-logic additions (
filters.jsor newutils/works.js)buildWorkUrl(work)— already exists asbestEdition; may need aworkPageUrlvariantisReadable(work)— checkebook_access >= borrowable(already used inbestEdition)Acceptance criteria
ol-book-cardhas a ▾ chevron; clicking it expands the card with additional metadataol-book-carddeclares_expandedreactive property and emitsol-card-expand