[BD-46] refactor Pagination component - #1911
Conversation
|
Thanks for the pull request, @viktorrusakov! When this pull request is ready, tag your edX technical lead. |
✅ Deploy Preview for paragon-openedx ready!Built without sensitive environment variables
To edit notification comments on pull requests, go to your Netlify site configuration. |
4aa622d to
0fbded8
Compare
0fbded8 to
ea7b140
Compare
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## master #1911 +/- ##
==========================================
+ Coverage 92.82% 92.86% +0.03%
==========================================
Files 235 246 +11
Lines 4237 4245 +8
Branches 1029 1018 -11
==========================================
+ Hits 3933 3942 +9
+ Misses 300 299 -1
Partials 4 4
☔ View full report in Codecov by Sentry. |
ea7b140 to
d90f3ce
Compare
d90f3ce to
0895385
Compare
0895385 to
43ba12f
Compare
| import Pagination from '../Pagination'; | ||
| import { ArrowBackIos, ArrowForwardIos } from '../../icons'; | ||
|
|
||
| function TablePaginationMinimal() { |
There was a problem hiding this comment.
Can we add propTypes for this component?
There was a problem hiding this comment.
This component does not receive any props, so I don't think propTypes are needed here
efc00db to
1ec4fa7
Compare
adamstankiewicz
left a comment
There was a problem hiding this comment.
Overall, this looks great! Left a few comments and clarifying questions. Also, sanity check... will we likely want to release these changes as new major version release (i.e., breaking change)?
I'm seeing at least the following possible breaking changes for consumers:
- Removed SCSS variables for
Paginationthat theme authors may have been relying on. iconsprop now expects elements (e.g., icons imported from@edx/paragon/iconsrather than nodes).
| leftIcon: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), | ||
| rightIcon: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), |
There was a problem hiding this comment.
[clarification] Is this intended to be a breaking change from what's supported today? In the current state, consumers can technically pass any node rather than just an element.
That said, it only looks like this impacts 1 usage of Pagination though as a breaking change according to usage insights; I think it's probably fine to go this route. That 1 usage should be using the buttonLabels instead of passing a node with <Icon> and <span className="sr-only">...</span> elements. Everything in the sr-only span really should probably be in the buttonLabels prop.
There was a problem hiding this comment.
Good catch! That was a while ago, took me some time to remember why I did this haha, I was definitely trying to avoid making breaking changes, but here it's almost unavoidable I think.
The reason is that in original implementation these icon props worked only for the default variant of Pagination, i.e. they were ignored for all other variants and you could not override icons for secondary variant for example. I felt like this definitely should be fixed during this refactoring and I don't really see any other way, because we use IconButtons for other variants and they expect our icon instances, not any node.
We could probably add some magic with our withDeprecatedProps HOC to support both behaviours, but I think that would be pretty ugly... not sure if it's worth doing that, I feel like this breaking change is pretty minor and we can go with it to keep this component clean.
| previous: 'Previous', | ||
| next: 'Next', | ||
| page: 'Page', | ||
| currentPage: 'Current Page', | ||
| pageOfCount: 'of', |
There was a problem hiding this comment.
[curious] Is this a place where we should add i18n support to Pagination (could be a follow-up issue).
There was a problem hiding this comment.
Yeah, it crossed my mind, but I think in this case it's harder than it seems because we use these strings in a way that does not support translation I think, e.g. the screen reader text for the component is generated as follows:
const getScreenReaderText = () => `${buttonLabels.page} ${currentPage}, ${buttonLabels.currentPage}, ${buttonLabels.pageOfCount} ${pageCount}`;(this would generate following text Page 3, Current Page, of 20)
I'm pretty sure that for it to be translated correctly, the whole string has to be marked for translation, not just parts of it (in this case it would be page, currentPage and pageOfCount strings)
So yeah, I'm not sure that just marking these props for i18n would be useful
There was a problem hiding this comment.
I think we might need to make another breaking change here to correctly support i18n, i.e. make consumers pass the whole text instead of parts of it, for example add screenReaderText prop and allow adding placeholders there, e.g. default value would be Page {currentPage}, Current Page, of {totalPagesCount} where we have predefined placeholders that will be replaced by the component with correct values. What do you think?
| export const PAGINATION_BUTTON_LABEL_NEXT = 'Next'; | ||
| export const PAGINATION_BUTTON_LABEL_PAGE = 'Page'; | ||
| export const PAGINATION_BUTTON_LABEL_CURRENT_PAGE = 'Current Page'; | ||
| export const PAGINATION_BUTTON_LABEL_PAGE_OF_COUNT = 'of'; | ||
| export const PAGINATION_BUTTON_ICON_BUTTON_NEXT_ALT = 'Go to next page'; | ||
| export const PAGINATION_BUTTON_ICON_BUTTON_PREV_ALT = 'Go to previous page'; |
There was a problem hiding this comment.
Also asked in another comment related to Pagination's default props, but wondering if these default English strings should be marked for i18n translation?
| import { greaterThan } from '../utils/propTypes'; | ||
| import { ChevronLeft, ChevronRight } from '../../icons'; | ||
|
|
||
| function Pagination(props) { |
There was a problem hiding this comment.
Nice cleanup of the root Pagination component and abstracting out all its variants to subcomponents. Much cleaner and simpler to reason about!
| @@ -0,0 +1,7 @@ | |||
| export { default as Ellipsis } from './Ellipsis'; | |||
There was a problem hiding this comment.
tiniest of nits: this could be a vanilla .js file as it doesn't render JSX
| PAGINATION_BUTTON_LABEL_NEXT, | ||
| PAGINATION_BUTTON_LABEL_PAGE, | ||
| } from './Pagination'; | ||
| } from './Pagination/constants'; |
There was a problem hiding this comment.
nit: i wonder if it's worth sticking to convention in this file of exporting constants from the top-level component file? Could consider adding the following to ./src/Pagination/index.jsx:
export * from './constants';There was a problem hiding this comment.
Yeah, makes sense, updated, thanks!
b0a4053 to
ba7deae
Compare
|
We plan to release all breaking changes at the same time, a new PR is open here. |
|
@viktorrusakov Even though your pull request wasn’t merged, please take a moment to answer a two question survey so we can improve your experience in the future. |
Description
Refactors
Paginationcomponent to fix its style and API issues (and to improve it overall to ease maintenance).Note: should be merged after #1190 and edx/brand-edx.org#49, as they would fix ongoing issues with styles.
Deploy Preview
https://deploy-preview-1911--paragon-openedx.netlify.app/components/pagination/
Merge Checklist
exampleapp?wittjeffandadamstankiewiczas reviewers on this PR.Post-merge Checklist