Skip to content

Commit fd5f2cd

Browse files
lokeshclaudepre-commit-ci[bot]cdrini
authored
Implement pagination web component on Trending page (#12035)
* refactor: Rename pagination event to ol-pagination-change Rename custom event from update:page to ol-pagination-change with structured detail object. Add self-update of currentPage with cancelable support. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: Update design template for ol-pagination-change event Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: Enhance OlPagination documentation and examples Updated the OlPagination component's documentation to clarify the behavior of the baseUrl property and its fallback to the current page URL. Improved examples to demonstrate analytics tracking and the handling of the ol-pagination-change event. Adjusted text for better clarity on navigation options. * feat: Introduce OlPagination component and update trending template Added a new OlPagination component for improved pagination functionality. Updated the trending template to utilize the new component, replacing the previous pager implementation. Enhanced CSS for pagination styling and adjusted mybooks list margin for better layout. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update openlibrary/templates/trending.html --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Drini Cami <cdrini@gmail.com>
1 parent 68d8b8e commit fd5f2cd

7 files changed

Lines changed: 86 additions & 33 deletions

File tree

openlibrary/components/lit/OlPagination.js

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ import { LitElement, html, css } from 'lit';
77
*
88
* @prop {Number} totalPages - Total number of pages
99
* @prop {Number} currentPage - Currently selected page (1-indexed)
10-
* @prop {String} baseUrl - Optional base URL for generating page links. When provided,
11-
* renders anchor tags for SEO-friendly navigation. When omitted,
12-
* renders buttons and emits events.
10+
* @prop {String} baseUrl - Optional base URL for generating page links. When omitted,
11+
* falls back to the current page URL, preserving all existing
12+
* query parameters (similar to changequery). Always renders
13+
* anchor tags for SEO-friendly navigation.
1314
* @prop {String} labelPreviousPage - Aria label for "previous page" button (default: "Go to previous page")
1415
* @prop {String} labelNextPage - Aria label for "next page" button (default: "Go to next page")
1516
* @prop {String} labelGoToPage - Aria label template for page buttons, use {page} as placeholder
@@ -21,14 +22,20 @@ import { LitElement, html, css } from 'lit';
2122
* @fires ol-pagination-change - Fired when a page is selected. detail: { page: Number }
2223
*
2324
* @example
24-
* <!-- Event-based -->
25+
* <!-- Uses current page URL, preserving query params -->
2526
* <ol-pagination total-pages="50" current-page="1"></ol-pagination>
2627
*
2728
* @example
28-
* <!-- URL-based -->
29+
* <!-- Explicit base URL -->
2930
* <ol-pagination total-pages="50" current-page="1" base-url="/search?q=hello"></ol-pagination>
3031
*
3132
* @example
33+
* <!-- Intercept navigation with event -->
34+
* <ol-pagination total-pages="50" current-page="1"
35+
* @ol-pagination-change=${(e) => { e.preventDefault(); handlePage(e.detail.page); }}
36+
* ></ol-pagination>
37+
*
38+
* @example
3239
* <!-- With translated labels -->
3340
* <ol-pagination
3441
* total-pages="50"
@@ -73,32 +80,33 @@ export class OlPagination extends LitElement {
7380
border: 1px solid transparent;
7481
border-radius: 4px;
7582
background: transparent;
76-
color: #444;
83+
color: var(--darker-grey, #444);
7784
cursor: pointer;
7885
text-decoration: none;
7986
}
8087
8188
.pagination-item:hover:not([aria-disabled="true"]):not([aria-current="page"]) {
82-
background: rgba(0, 0, 0, 0.1);
89+
background: var(--icon-link-grey, rgba(0, 0, 0, 0.1));
8390
}
8491
8592
.pagination-item:focus {
8693
outline: none;
8794
}
8895
8996
.pagination-item:focus-visible {
90-
outline: 2px solid #5B8DD9;
97+
outline: 2px solid var(--color-focus-ring, #5B8DD9);
9198
outline-offset: 2px;
9299
}
93100
94101
.pagination-item[aria-current="page"] {
95-
border-color: #ddd;
102+
border-color: var(--lighter-grey, #ddd);
103+
background-color: var(--lightest-grey, #eee);
96104
cursor: default;
97105
user-select: none;
98106
}
99107
100108
.pagination-item[aria-disabled="true"] {
101-
color: #ddd;
109+
color: var(--lighter-grey, #ddd);
102110
cursor: not-allowed;
103111
}
104112
@@ -110,7 +118,7 @@ export class OlPagination extends LitElement {
110118
display: flex;
111119
align-items: center;
112120
justify-content: center;
113-
color: #aaa;
121+
color: var(--mid-grey, #aaa);
114122
cursor: default;
115123
user-select: none;
116124
}
@@ -149,15 +157,15 @@ export class OlPagination extends LitElement {
149157

150158
/**
151159
* Build URL for a specific page number.
152-
* Returns null if baseUrl is not set.
160+
* Uses baseUrl if provided, otherwise falls back to the current window location.
161+
* This preserves all existing query parameters (like changequery() does).
153162
* @param {Number} page - The page number
154-
* @returns {String|null} The URL for the page, or null if baseUrl not set
163+
* @returns {String|null} The URL for the page
155164
*/
156165
_getPageUrl(page) {
157-
if (!this.baseUrl) return null;
158-
159166
try {
160-
const url = new URL(this.baseUrl, window.location.origin);
167+
const base = this.baseUrl || window.location.href;
168+
const url = new URL(base, window.location.origin);
161169
if (page === 1) {
162170
url.searchParams.delete('page');
163171
} else {
@@ -254,6 +262,7 @@ export class OlPagination extends LitElement {
254262
/**
255263
* Handle click on anchor-based page links.
256264
* Dispatches the ol-pagination-change event to allow interception.
265+
* If the event is cancelled via preventDefault(), anchor navigation is also prevented.
257266
* @param {Event} e - Click event
258267
* @param {Number} page - The page number
259268
*/
@@ -265,6 +274,10 @@ export class OlPagination extends LitElement {
265274
cancelable: true,
266275
});
267276
this.dispatchEvent(event);
277+
if (event.defaultPrevented) {
278+
e.preventDefault();
279+
this.currentPage = page;
280+
}
268281
}
269282

270283
/**

openlibrary/i18n/messages.pot

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,26 @@ msgstr ""
491491
msgid "My Book Review"
492492
msgstr ""
493493

494+
#: OlPagination.html
495+
msgid "Go to previous page"
496+
msgstr ""
497+
498+
#: OlPagination.html
499+
msgid "Go to next page"
500+
msgstr ""
501+
502+
#: OlPagination.html
503+
msgid "Go to page {page}"
504+
msgstr ""
505+
506+
#: OlPagination.html
507+
msgid "Page {page}, current page"
508+
msgstr ""
509+
510+
#: OlPagination.html type/edition/view.html type/work/view.html
511+
msgid "Pagination"
512+
msgstr ""
513+
494514
#: Pager.html Pager_loanhistory.html
495515
msgid "First"
496516
msgstr ""
@@ -1813,18 +1833,19 @@ msgid ""
18131833
msgstr ""
18141834

18151835
#: design.html
1816-
msgid "Event-based"
1836+
msgid "Analytics tracking"
18171837
msgstr ""
18181838

18191839
#: design.html
18201840
#, python-format
18211841
msgid ""
18221842
"When a page is clicked, the component fires an %(event_name)s event with "
1823-
"the page number in %(event_detail)s."
1843+
"the page number in %(event_detail)s. Use this to send analytics before "
1844+
"the browser navigates."
18241845
msgstr ""
18251846

18261847
#: design.html
1827-
msgid "Selected page:"
1848+
msgid "Last tracked page:"
18281849
msgstr ""
18291850

18301851
#: design.html
@@ -1833,8 +1854,8 @@ msgstr ""
18331854

18341855
#: design.html
18351856
msgid ""
1836-
"When base-url is provided, pagination renders anchor tags for SEO-"
1837-
"friendly links."
1857+
"By default, pagination renders anchor tags using the current page URL, "
1858+
"preserving all query parameters. Use base-url to override the URL."
18381859
msgstr ""
18391860

18401861
#: design.html
@@ -7938,10 +7959,6 @@ msgstr ""
79387959
msgid "Format"
79397960
msgstr ""
79407961

7941-
#: type/edition/view.html type/work/view.html
7942-
msgid "Pagination"
7943-
msgstr ""
7944-
79457962
#: type/edition/view.html type/work/view.html
79467963
msgid "Number of pages"
79477964
msgstr ""
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
$def with (page, total_pages)
2+
3+
$if total_pages > 1:
4+
<ol-pagination
5+
total-pages="$total_pages"
6+
current-page="$page"
7+
label-previous-page="$_('Go to previous page')"
8+
label-next-page="$_('Go to next page')"
9+
label-go-to-page="$_('Go to page {page}')"
10+
label-current-page="$_('Page {page}, current page')"
11+
label-pagination="$_('Pagination')"
12+
></ol-pagination>

openlibrary/templates/design.html

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,24 +25,29 @@ <h2 class="design-pattern__title">$_("Pagination component")</h2>
2525
</div>
2626
<div class="design-pattern__content">
2727
<section class="example">
28-
<h3 class="example__title">$_("Event-based")</h3>
29-
<p>$:_("When a page is clicked, the component fires an %(event_name)s event with the page number in %(event_detail)s.", event_name="<code>ol-pagination-change</code>", event_detail="<code>event.detail.page</code>")</p>
30-
<code class="example__code">&lt;ol-pagination total-pages="10" current-page="1"&gt;&lt;/ol-pagination&gt;</code>
28+
<h3 class="example__title">$_("Analytics tracking")</h3>
29+
<p>$:_("When a page is clicked, the component fires an %(event_name)s event with the page number in %(event_detail)s. Use this to send analytics before the browser navigates.", event_name="<code>ol-pagination-change</code>", event_detail="<code>event.detail.page</code>")</p>
30+
<code class="example__code">document.addEventListener('ol-pagination-change', (e) => {
31+
navigator.sendBeacon('/analytics', JSON.stringify({
32+
category: 'Pager',
33+
action: 'Page ' + e.detail.page,
34+
}));
35+
});</code>
3136
<div class="example__output">
3237
<ol-pagination id="demo-pagination" total-pages="10" current-page="1"></ol-pagination>
3338
</div>
34-
<p>$_("Selected page:"): <strong id="demo-selected-page">1</strong></p>
39+
<p>$_("Last tracked page:"): <strong id="demo-selected-page">-</strong></p>
3540
<script>
3641
document.getElementById('demo-pagination').addEventListener('ol-pagination-change', (e) => {
42+
e.preventDefault();
3743
document.getElementById('demo-selected-page').textContent = e.detail.page;
38-
e.target.setAttribute('current-page', e.detail.page);
3944
});
4045
</script>
4146
</section>
4247

4348
<section class="example">
4449
<h3 class="example__title">$_("URL-based Navigation")</h3>
45-
<p>$_("When base-url is provided, pagination renders anchor tags for SEO-friendly links.")</p>
50+
<p>$_("By default, pagination renders anchor tags using the current page URL, preserving all query parameters. Use base-url to override the URL.")</p>
4651
<code class="example__code">&lt;ol-pagination total-pages="50" current-page="5" base-url="/search?q=example"&gt;&lt;/ol-pagination&gt;</code>
4752
<ol-pagination total-pages="50" current-page="5" base-url="/search?q=example"></ol-pagination>
4853
</section>

openlibrary/templates/trending.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ <h1>$_('Trending Books'): $(pages[mode])</h1>
3131
$:macros.SearchResultsWork(entry['work'], extra=extra, availability=entry['work'].get('availability'), seq_index=loop.index0)
3232
</ul>
3333
</div>
34-
<div class="pager">
35-
$:macros.Pager(page, 200, results_per_page=20)
34+
<div class="ol-pagination-wrapper">
35+
$:macros.OlPagination(page, total_pages=200 // 20)
3636
</div>
3737
</div>

static/css/components/mybooks-list.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242

4343
.mybooks-list {
4444
overflow-wrap: anywhere;
45+
margin-bottom: 12px;
4546
}
4647

4748
.chip-group + .mybooks-list {

static/css/components/pagination.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,8 @@
3636
margin-right: 10px;
3737
background-color: var(--lightest-grey);
3838
}
39+
40+
.ol-pagination-wrapper {
41+
display: flex;
42+
justify-content: center;
43+
}

0 commit comments

Comments
 (0)