1- import type { Dispatch , SetStateAction } from 'react' ;
2- import { useMemo } from 'react' ;
1+ import type { Dispatch , HTMLAttributes , SetStateAction } from 'react' ;
2+ import { useId , useMemo } from 'react' ;
33
4- import { Box , type BoxProps } from '../Box' ;
54import { Chevron } from '../Chevron' ;
65
76type ItemsPerPage = 25 | 50 | 100 ;
87
9- export type PaginationProps = BoxProps & {
8+ export type PaginationProps = {
109 count : number ;
1110 current ?: number ;
1211 divider ?: boolean ;
@@ -23,7 +22,7 @@ export type PaginationProps = BoxProps & {
2322 } ) => string ;
2423 onSetCurrent ?: Dispatch < SetStateAction < number > > ;
2524 onSetItemsPerPage ?: Dispatch < SetStateAction < ItemsPerPage > > ;
26- } ;
25+ } & HTMLAttributes < HTMLElement > ;
2726
2827const defaultItemsPerPageLabel = ( ) => 'Items per page:' ;
2928
@@ -41,7 +40,7 @@ const defaultShowingResultsLabel = ({
4140 count ,
4241 ) } of ${ count } `;
4342
44- const itemsPerPageOptions = [ 25 , 50 , 100 ] as ItemsPerPage [ ] ;
43+ const itemsPerPageOptions = [ 25 , 50 , 100 ] as const ;
4544
4645const Pagination = ( {
4746 count,
@@ -54,6 +53,9 @@ const Pagination = ({
5453 divider,
5554 ...props
5655} : PaginationProps ) => {
56+ const paginationResultLabelId = useId ( ) ;
57+ const itemsPerPageLabelId = useId ( ) ;
58+
5759 const hasItemsPerPageSelection = itemsPerPageOptions . length > 1 ;
5860 const currentPage = Math . floor ( current / itemsPerPage ) ;
5961 const pages = Math . ceil ( count / itemsPerPage ) ;
@@ -97,73 +99,91 @@ const Pagination = ({
9799 } ;
98100
99101 return (
100- < Box is = 'nav' rcx-pagination rcx-pagination--divider = { divider } { ...props } >
102+ < nav
103+ className = { [
104+ 'rcx-box rcx-box--full rcx-pagination' ,
105+ divider && 'rcx-pagination--divider' ,
106+ ]
107+ . filter ( Boolean )
108+ . join ( ' ' ) }
109+ aria-label = 'Pagination Navigation'
110+ { ...props }
111+ >
101112 { hasItemsPerPageSelection && (
102- < Box rcx-pagination__left >
103- < Box is = 'span' rcx-pagination__label >
113+ < div className = ' rcx-pagination__left' >
114+ < span className = ' rcx-pagination__label' id = { itemsPerPageLabelId } >
104115 { itemsPerPageLabel ( renderingContext ) }
105- </ Box >
106- < Box is = 'ol' rcx-pagination__list >
116+ </ span >
117+ < ol
118+ className = 'rcx-box rcx-box--full rcx-pagination__list'
119+ aria-labelledby = { itemsPerPageLabelId }
120+ >
107121 { itemsPerPageOptions . map ( ( itemsPerPageOption ) => (
108- < Box key = { itemsPerPageOption } is = 'li' rcx-pagination__list-item >
109- < Box
110- is = 'button'
111- rcx-pagination__link
122+ < li
123+ key = { itemsPerPageOption }
124+ className = 'rcx-pagination__list-item'
125+ >
126+ < button
127+ className = 'rcx-box rcx-box--full rcx-pagination__link'
112128 tabIndex = { itemsPerPage === itemsPerPageOption ? - 1 : 0 }
113129 disabled = { itemsPerPage === itemsPerPageOption }
130+ aria-label = { `Show ${ itemsPerPageOption } items per page` }
114131 onClick = { handleSetItemsPerPageLinkClick ( itemsPerPageOption ) }
115132 >
116133 { itemsPerPageOption }
117- </ Box >
118- </ Box >
134+ </ button >
135+ </ li >
119136 ) ) }
120- </ Box >
121- </ Box >
137+ </ ol >
138+ </ div >
122139 ) }
123- < Box rcx-pagination__right >
124- < Box is = 'span' rcx-pagination__label >
140+ < div className = ' rcx-pagination__right' >
141+ < span className = ' rcx-pagination__label' id = { paginationResultLabelId } >
125142 { showingResultsLabel ( renderingContext ) }
126- </ Box >
127- < Box is = 'ol' rcx-pagination__list >
128- < Box is = 'li' rcx-pagination__list-item >
129- < Box
130- is = 'button'
131- rcx-pagination__back
143+ </ span >
144+ < ol
145+ className = 'rcx-box rcx-box--full rcx-pagination__list'
146+ aria-labelledby = { paginationResultLabelId }
147+ >
148+ < li className = 'rcx-pagination__list-item' >
149+ < button
150+ className = 'rcx-box rcx-box--full rcx-pagination__back'
132151 disabled = { currentPage === 0 }
152+ aria-label = 'Previous page'
133153 onClick = { handleSetPageLinkClick ( currentPage - 1 ) }
134154 >
135155 < Chevron left size = 'x16' />
136- </ Box >
137- </ Box >
156+ </ button >
157+ </ li >
138158 { displayedPages . map ( ( page , i ) => (
139- < Box key = { i } is = 'li' rcx-pagination__list-item >
159+ < li key = { i } className = ' rcx-pagination__list-item' >
140160 { page === '⋯' ? (
141161 '⋯'
142162 ) : (
143- < Box
144- is = 'button'
145- rcx-pagination__link
163+ < button
164+ className = 'rcx-box rcx-box--full rcx-pagination__link'
146165 disabled = { currentPage === page }
147- onClick = { handleSetPageLinkClick ( page as number ) }
166+ aria-label = { `Page ${ Number ( page ) + 1 } ` }
167+ onClick = { handleSetPageLinkClick ( Number ( page ) ) }
148168 >
149- { ( page as number ) + 1 }
150- </ Box >
169+ { Number ( page ) + 1 }
170+ </ button >
151171 ) }
152- </ Box >
172+ </ li >
153173 ) ) }
154- < Box is = 'li' rcx-pagination__list-item >
155- < Box
156- is = 'button'
157- rcx-pagination__forward
174+ < li className = 'rcx-pagination__list-item' >
175+ < button
176+ className = 'rcx-box rcx-box--full rcx-pagination__forward'
158177 disabled = { currentPage === pages - 1 }
178+ aria-label = 'Next page'
159179 onClick = { handleSetPageLinkClick ( currentPage + 1 ) }
160180 >
161181 < Chevron right size = 'x16' />
162- </ Box >
163- </ Box >
164- </ Box >
165- </ Box >
166- </ Box >
182+ </ button >
183+ </ li >
184+ </ ol >
185+ </ div >
186+ </ nav >
167187 ) ;
168188} ;
169189
0 commit comments