Skip to content

Commit e1e8509

Browse files
authored
Fix paging overflow and text placement (#40)
- fixed row size and overflow behaviour for Paging component so that it does not always show a horizontal scrollbar regardless of the available width (for example, when wrapping a table inside a div with `overflow` property set to `auto`); - paging info text now occupies the whole row in case there are no page buttons to be rendered
1 parent e882348 commit e1e8509

3 files changed

Lines changed: 84 additions & 75 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Fixed
11+
12+
- Fixed row size and overflow behaviour for Paging component so that it does not always show a horizontal scrollbar regardless of the available width
13+
- The paging text will now occupy the whole row in case there are no page buttons to be rendered
14+
1015
## [2.8.1] - 2023-09-19
1116

1217
### Fixed

cypress/cypress/component/Paging/Paging.cy.tsx

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ describe("Paging.cy.tsx", () => {
2222
);
2323

2424
// Check pages per item dropdown
25-
cy.get("[data-cy-root] > .row > .col-6:first-of-type > .btn-group > button.dropdown-toggle")
25+
cy.get("[data-cy-root] > .container-fluid > .row > .col-6:first-of-type > .btn-group > button.dropdown-toggle")
2626
.should("have.text", itemsPerPage.toString())
2727
.click();
28-
cy.get("[data-cy-root] > .row > .col-6:first-of-type > .btn-group > .dropdown-menu > h6").should(
28+
cy.get("[data-cy-root] > .container-fluid > .row > .col-6:first-of-type > .btn-group > .dropdown-menu > h6").should(
2929
"have.text",
3030
translations.itemsPerPageDropdown,
3131
);
32-
cy.get("[data-cy-root] > .row > .col-6:first-of-type > .btn-group > .dropdown-menu > .dropdown-item").then(
32+
cy.get("[data-cy-root] > .container-fluid > .row > .col-6:first-of-type > .btn-group > .dropdown-menu > .dropdown-item").then(
3333
(items: JQuery<HTMLElement>) => {
3434
expect(items.map((_, item) => item.innerText).toArray(), "possible items per page").to.deep.eq(
3535
[25, 50, 100, 200, itemsPerPage].sort((a, b) => a - b).map((itemNumber): string => itemNumber.toString()),
@@ -40,7 +40,7 @@ describe("Paging.cy.tsx", () => {
4040
);
4141

4242
// Check current page/items text
43-
cy.get("[data-cy-root] > .row > .col-6:first-of-type > span.small").should(
43+
cy.get("[data-cy-root] > .container-fluid > .row > .col-6:first-of-type > span.small").should(
4444
"have.text",
4545
translations.showedItemsText
4646
.replace("{from}", (currentPage * itemsPerPage - itemsPerPage + 1).toString())
@@ -49,18 +49,20 @@ describe("Paging.cy.tsx", () => {
4949
);
5050

5151
// Check pagination buttons
52-
cy.get("[data-cy-root] > .row > .col-6:nth-of-type(2) > .btn-group > button.btn").then((items: JQuery<HTMLElement>) => {
53-
expect(items.length, "navigation buttons count").to.eq(Math.min(7, pages) + 4);
54-
cy.wrap(items.filter((_, item) => item.innerText === "<<")).click();
55-
cy.get("@setCurrentPage").should("be.calledOnceWith", 1);
56-
cy.wrap(items.filter((_, item) => item.innerText === "<")).click();
57-
cy.get("@setCurrentPage").should("be.calledWith", currentPage - 1);
58-
cy.wrap(items.filter((_, item) => item.innerText === (currentPage - 1).toString())).click();
59-
cy.get("@setCurrentPage").should("be.calledWith", currentPage - 1);
60-
cy.wrap(items.filter((_, item) => item.innerText === ">")).click();
61-
cy.get("@setCurrentPage").should("be.calledWith", currentPage + 1);
62-
cy.wrap(items.filter((_, item) => item.innerText === ">>")).click();
63-
cy.get("@setCurrentPage").should("be.calledWith", pages);
64-
});
52+
cy.get("[data-cy-root] > .container-fluid > .row > .col-6:nth-of-type(2) > .btn-group > button.btn").then(
53+
(items: JQuery<HTMLElement>) => {
54+
expect(items.length, "navigation buttons count").to.eq(Math.min(7, pages) + 4);
55+
cy.wrap(items.filter((_, item) => item.innerText === "<<")).click();
56+
cy.get("@setCurrentPage").should("be.calledOnceWith", 1);
57+
cy.wrap(items.filter((_, item) => item.innerText === "<")).click();
58+
cy.get("@setCurrentPage").should("be.calledWith", currentPage - 1);
59+
cy.wrap(items.filter((_, item) => item.innerText === (currentPage - 1).toString())).click();
60+
cy.get("@setCurrentPage").should("be.calledWith", currentPage - 1);
61+
cy.wrap(items.filter((_, item) => item.innerText === ">")).click();
62+
cy.get("@setCurrentPage").should("be.calledWith", currentPage + 1);
63+
cy.wrap(items.filter((_, item) => item.innerText === ">>")).click();
64+
cy.get("@setCurrentPage").should("be.calledWith", pages);
65+
},
66+
);
6567
});
6668
});

src/lib/Paging/Paging.tsx

Lines changed: 60 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -45,66 +45,68 @@ function Paging({
4545
);
4646

4747
return (
48-
<Row style={{ marginBottom: "20px" }}>
49-
<Col xs={6}>
50-
{pagingPossible && (
51-
<UncontrolledButtonDropdown>
52-
<DropdownToggle caret color="link" size="sm">
53-
{currentItemsPerPage}
54-
</DropdownToggle>
55-
<DropdownMenu>
56-
<DropdownItem header>{translations.itemsPerPageDropdown}</DropdownItem>
57-
{possibleItemsPerPage.map((pageItemCount) => (
58-
<DropdownItem key={`pageItemCount_${pageItemCount}`} onClick={() => setItemsPerPage(pageItemCount)}>
59-
{pageItemCount}
60-
</DropdownItem>
61-
))}
62-
</DropdownMenu>
63-
</UncontrolledButtonDropdown>
64-
)}
65-
<span className="small ml-2">
66-
{translations.showedItemsText
67-
.replace("{from}", ((currentPage - 1) * currentItemsPerPage + 1).toString())
68-
.replace("{to}", ((currentPage - 1) * currentItemsPerPage + currentRecordCount).toString())
69-
.replace("{total}", totalRecords.toString())}
70-
</span>
71-
</Col>
48+
<div className="container-fluid">
49+
<Row style={{ marginBottom: "20px" }}>
50+
<Col xs={pagingPossible && currentItemsPerPage < totalRecords ? 6 : 12} style={{ paddingLeft: 0 }}>
51+
{pagingPossible && (
52+
<UncontrolledButtonDropdown>
53+
<DropdownToggle caret color="link" size="sm">
54+
{currentItemsPerPage}
55+
</DropdownToggle>
56+
<DropdownMenu>
57+
<DropdownItem header>{translations.itemsPerPageDropdown}</DropdownItem>
58+
{possibleItemsPerPage.map((pageItemCount) => (
59+
<DropdownItem key={`pageItemCount_${pageItemCount}`} onClick={() => setItemsPerPage(pageItemCount)}>
60+
{pageItemCount}
61+
</DropdownItem>
62+
))}
63+
</DropdownMenu>
64+
</UncontrolledButtonDropdown>
65+
)}
66+
<span className="small ml-2">
67+
{translations.showedItemsText
68+
.replace("{from}", ((currentPage - 1) * currentItemsPerPage + 1).toString())
69+
.replace("{to}", ((currentPage - 1) * currentItemsPerPage + currentRecordCount).toString())
70+
.replace("{total}", totalRecords.toString())}
71+
</span>
72+
</Col>
7273

73-
{pagingPossible && currentItemsPerPage < totalRecords && (
74-
<Col xs={6} style={{ textAlign: "right" }}>
75-
<ButtonGroup size="sm">
76-
{showControls && (
77-
<Button color="secondary" outline disabled={currentPage === 1} onClick={() => setCurrentPage(1)}>
78-
{"<<"}
79-
</Button>
80-
)}
81-
{showControls && (
82-
<Button color="secondary" outline disabled={currentPage === 1} onClick={() => setCurrentPage(currentPage - 1)}>
83-
{"<"}
84-
</Button>
85-
)}
86-
{Array.from(Array(maxPage + 1).keys())
87-
.filter((page) => page > firstPageShown)
88-
.slice(0, maxPagesShown)
89-
.map((page) => (
90-
<Button key={page} outline={currentPage !== page} color="secondary" onClick={() => setCurrentPage(page)}>
91-
{page}
74+
{pagingPossible && currentItemsPerPage < totalRecords && (
75+
<Col xs={6} style={{ textAlign: "right", paddingRight: 0 }}>
76+
<ButtonGroup size="sm">
77+
{showControls && (
78+
<Button color="secondary" outline disabled={currentPage === 1} onClick={() => setCurrentPage(1)}>
79+
{"<<"}
9280
</Button>
93-
))}
94-
{showControls && (
95-
<Button color="secondary" outline disabled={currentPage === maxPage} onClick={() => setCurrentPage(currentPage + 1)}>
96-
{">"}
97-
</Button>
98-
)}
99-
{showControls && (
100-
<Button color="secondary" outline disabled={currentPage === maxPage} onClick={() => setCurrentPage(maxPage)}>
101-
{">>"}
102-
</Button>
103-
)}
104-
</ButtonGroup>
105-
</Col>
106-
)}
107-
</Row>
81+
)}
82+
{showControls && (
83+
<Button color="secondary" outline disabled={currentPage === 1} onClick={() => setCurrentPage(currentPage - 1)}>
84+
{"<"}
85+
</Button>
86+
)}
87+
{Array.from(Array(maxPage + 1).keys())
88+
.filter((page) => page > firstPageShown)
89+
.slice(0, maxPagesShown)
90+
.map((page) => (
91+
<Button key={page} outline={currentPage !== page} color="secondary" onClick={() => setCurrentPage(page)}>
92+
{page}
93+
</Button>
94+
))}
95+
{showControls && (
96+
<Button color="secondary" outline disabled={currentPage === maxPage} onClick={() => setCurrentPage(currentPage + 1)}>
97+
{">"}
98+
</Button>
99+
)}
100+
{showControls && (
101+
<Button color="secondary" outline disabled={currentPage === maxPage} onClick={() => setCurrentPage(maxPage)}>
102+
{">>"}
103+
</Button>
104+
)}
105+
</ButtonGroup>
106+
</Col>
107+
)}
108+
</Row>
109+
</div>
108110
);
109111
}
110112

0 commit comments

Comments
 (0)