From e6e5a7b6cda158f16cf0d86787130877b9c22a75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20S=C3=A1ros?= Date: Wed, 13 Nov 2024 15:57:12 +0100 Subject: [PATCH] fix(shared-types,ui-pagination): pagination indicators have spacing and coded as a list for a11y --- .../src/ComponentThemeVariables.ts | 4 ++ .../src/Pagination/PaginationButton/index.tsx | 23 +++++----- .../__new-tests__/Pagination.test.tsx | 10 +++-- .../ui-pagination/src/Pagination/index.tsx | 7 +-- .../ui-pagination/src/Pagination/props.ts | 4 +- .../ui-pagination/src/Pagination/styles.ts | 9 +++- .../ui-pagination/src/Pagination/theme.ts | 45 +++++++++++++++++++ 7 files changed, 83 insertions(+), 19 deletions(-) create mode 100644 packages/ui-pagination/src/Pagination/theme.ts diff --git a/packages/shared-types/src/ComponentThemeVariables.ts b/packages/shared-types/src/ComponentThemeVariables.ts index 9097a575cd..3a9f07ae4e 100644 --- a/packages/shared-types/src/ComponentThemeVariables.ts +++ b/packages/shared-types/src/ComponentThemeVariables.ts @@ -949,6 +949,10 @@ export type PaginationPageInputTheme = { inputWidth: string } +export type PaginationTheme = { + pageIndicatorGap: Spacing['xSmall'] +} + export type PillTheme = { fontFamily: Typography['fontFamily'] padding: string | 0 diff --git a/packages/ui-pagination/src/Pagination/PaginationButton/index.tsx b/packages/ui-pagination/src/Pagination/PaginationButton/index.tsx index 34ea72cd2d..276dfbe996 100644 --- a/packages/ui-pagination/src/Pagination/PaginationButton/index.tsx +++ b/packages/ui-pagination/src/Pagination/PaginationButton/index.tsx @@ -59,17 +59,20 @@ class PaginationButton extends Component { const props = omitProps(this.props, PaginationButton.allowedProps, exclude) + // wrapped in an unstyled
  • for better a11y return ( - - {this.props.children} - +
  • + + {this.props.children} + +
  • ) } } diff --git a/packages/ui-pagination/src/Pagination/__new-tests__/Pagination.test.tsx b/packages/ui-pagination/src/Pagination/__new-tests__/Pagination.test.tsx index 351b859a3a..c5965f1e74 100644 --- a/packages/ui-pagination/src/Pagination/__new-tests__/Pagination.test.tsx +++ b/packages/ui-pagination/src/Pagination/__new-tests__/Pagination.test.tsx @@ -123,7 +123,9 @@ describe('', () => { it('by default', async () => { const { container } = render( - {buildPages(5)} +
      + {buildPages(5)} +
    ) @@ -134,7 +136,7 @@ describe('', () => { it('by default with more pages', async () => { const { container } = render( - {buildPages(8)} +
      {buildPages(8)}
    ) const axeCheck = await runAxeCheck(container) @@ -151,7 +153,7 @@ describe('', () => { labelLast="Last" withFirstAndLastButton > - {buildPages(8)} +
      {buildPages(8)}
    ) const axeCheck = await runAxeCheck(container) @@ -169,7 +171,7 @@ describe('', () => { withFirstAndLastButton showDisabledButtons > - {buildPages(8)} +
      {buildPages(8)}
    ) const axeCheck = await runAxeCheck(container) diff --git a/packages/ui-pagination/src/Pagination/index.tsx b/packages/ui-pagination/src/Pagination/index.tsx index 275d5ca0d4..a845e10ea9 100644 --- a/packages/ui-pagination/src/Pagination/index.tsx +++ b/packages/ui-pagination/src/Pagination/index.tsx @@ -36,6 +36,7 @@ import { PaginationArrowButton } from './PaginationArrowButton' import { PaginationPageInput } from './PaginationPageInput' import generateStyle from './styles' +import generateComponentTheme from './theme' import type { PaginationPageProps } from './PaginationButton/props' import type { PaginationArrowDirections } from './PaginationArrowButton/props' @@ -80,7 +81,7 @@ category: components --- **/ @withDeterministicId() -@withStyle(generateStyle, null) +@withStyle(generateStyle, generateComponentTheme) @testable() class Pagination extends Component { static readonly componentId = 'Pagination' @@ -103,7 +104,7 @@ class Pagination extends Component { currentPage: 1, siblingCount: 1, boundaryCount: 1, - ellipsis: '...', + ellipsis:
  • ...
  • , renderPageIndicator: (page: number) => page } @@ -408,7 +409,7 @@ class Pagination extends Component { ) ) } - return pages + return (
      {pages}
    ) } renderPages(currentPageIndex: number) { diff --git a/packages/ui-pagination/src/Pagination/props.ts b/packages/ui-pagination/src/Pagination/props.ts index 4dfbf564d0..0324d34b21 100644 --- a/packages/ui-pagination/src/Pagination/props.ts +++ b/packages/ui-pagination/src/Pagination/props.ts @@ -197,7 +197,9 @@ type PaginationProps = PaginationOwnProps & OtherHTMLAttributes & WithDeterministicIdProps -type PaginationStyle = ComponentStyle<'pagination' | 'pages'> +type PaginationStyle = ComponentStyle< + 'pagination' | 'pages' | 'pageIndicatorList' +> const propTypes: PropValidators = { children: Children.oneOf([PaginationButton]), diff --git a/packages/ui-pagination/src/Pagination/styles.ts b/packages/ui-pagination/src/Pagination/styles.ts index 0f2c1ea504..83dda5c1c0 100644 --- a/packages/ui-pagination/src/Pagination/styles.ts +++ b/packages/ui-pagination/src/Pagination/styles.ts @@ -22,6 +22,7 @@ * SOFTWARE. */ +import type { PaginationTheme } from '@instructure/shared-types' import type { PaginationStyle } from './props' /** @@ -34,8 +35,14 @@ import type { PaginationStyle } from './props' * @param {Object} state the state of the component, the style is applied to * @return {Object} The final style object, which will be used in the component */ -const generateStyle = (): PaginationStyle => { +const generateStyle = (componentTheme: PaginationTheme): PaginationStyle => { return { + pageIndicatorList: { + all: 'unset', + display: 'flex', + alignItems: 'center', + gap: componentTheme.pageIndicatorGap + }, pagination: { label: 'pagination', textAlign: 'center' diff --git a/packages/ui-pagination/src/Pagination/theme.ts b/packages/ui-pagination/src/Pagination/theme.ts new file mode 100644 index 0000000000..e91ee9f7d1 --- /dev/null +++ b/packages/ui-pagination/src/Pagination/theme.ts @@ -0,0 +1,45 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 - present Instructure, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import type { Theme } from '@instructure/ui-themes' +import { PaginationTheme } from '@instructure/shared-types' + +/** + * Generates the theme object for the component from the theme and provided additional information + * @param {Object} theme The actual theme object. + * @return {Object} The final theme object with the overrides and component variables + */ +const generateComponentTheme = (theme: Theme): PaginationTheme => { + const { spacing } = theme + + const componentVariables: PaginationTheme = { + pageIndicatorGap: spacing.xSmall + } + + return { + ...componentVariables + } +} + +export default generateComponentTheme