diff --git a/.changeset/shiny-ties-tan.md b/.changeset/shiny-ties-tan.md new file mode 100644 index 0000000000..7a6fe042b9 --- /dev/null +++ b/.changeset/shiny-ties-tan.md @@ -0,0 +1,6 @@ +--- +"@heroui/pagination": patch +"@heroui/use-pagination": patch +--- + +fixed pagination in RTL (#2858) diff --git a/packages/components/pagination/src/pagination.tsx b/packages/components/pagination/src/pagination.tsx index 07055cfa89..e8ebd0187b 100644 --- a/packages/components/pagination/src/pagination.tsx +++ b/packages/components/pagination/src/pagination.tsx @@ -40,6 +40,68 @@ const Pagination = forwardRef<"nav", PaginationProps>((props, ref) => { const isRTL = direction === "rtl"; + const renderChevronIcon = useCallback( + (key: PaginationItemType) => { + if ( + (key === PaginationItemType.PREV && !isRTL) || + (key === PaginationItemType.NEXT && isRTL) + ) { + return ; + } + + return ( + + ); + }, + [slots, isRTL], + ); + + const renderPrevItem = useCallback( + (value: PaginationItemValue) => { + return ( + + {renderChevronIcon(PaginationItemType.PREV)} + + ); + }, + [slots, classNames, loop, activePage, isRTL, total, getItemAriaLabel, onPrevious], + ); + + const renderNextItem = useCallback( + (value: PaginationItemValue) => { + return ( + + {renderChevronIcon(PaginationItemType.NEXT)} + + ); + }, + [slots, classNames, loop, activePage, isRTL, total, getItemAriaLabel, onNext], + ); + const renderItem = useCallback( (value: PaginationItemValue, index: number) => { const isBefore = index < range.indexOf(activePage); @@ -66,14 +128,8 @@ const Pagination = forwardRef<"nav", PaginationProps>((props, ref) => { } const itemChildren: Record = { - [PaginationItemType.PREV]: , - [PaginationItemType.NEXT]: ( - - ), + [PaginationItemType.PREV]: renderChevronIcon(PaginationItemType.PREV), + [PaginationItemType.NEXT]: renderChevronIcon(PaginationItemType.NEXT), [PaginationItemType.DOTS]: ( <> @@ -111,42 +167,10 @@ const Pagination = forwardRef<"nav", PaginationProps>((props, ref) => { } if (value === PaginationItemType.PREV) { - return ( - - - - ); + return renderPrevItem(value); } if (value === PaginationItemType.NEXT) { - return ( - - - - ); + return renderNextItem(value); } if (value === PaginationItemType.DOTS) { @@ -191,6 +215,12 @@ const Pagination = forwardRef<"nav", PaginationProps>((props, ref) => { slots, classNames, total, + getItemAriaLabel, + onNext, + onPrevious, + setPage, + renderPrevItem, + renderNextItem, ], ); diff --git a/packages/components/pagination/src/use-pagination.ts b/packages/components/pagination/src/use-pagination.ts index d01a5e311d..3a62fc9cd4 100644 --- a/packages/components/pagination/src/use-pagination.ts +++ b/packages/components/pagination/src/use-pagination.ts @@ -3,7 +3,6 @@ import type {Key, ReactNode, Ref} from "react"; import type {HTMLHeroUIProps, PropGetter} from "@heroui/system"; import {objectToDeps, Timer} from "@heroui/shared-utils"; -import {useLocale} from "@react-aria/i18n"; import { UsePaginationProps as UseBasePaginationProps, PaginationItemValue, @@ -195,10 +194,6 @@ export function usePagination(originalProps: UsePaginationProps) { const cursorTimer = useRef(); - const {direction} = useLocale(); - - const isRTL = direction === "rtl"; - const disableAnimation = originalProps?.disableAnimation ?? globalContext?.disableAnimation ?? false; const disableCursorAnimation = originalProps?.disableCursorAnimation ?? disableAnimation ?? false; @@ -321,7 +316,7 @@ export function usePagination(originalProps: UsePaginationProps) { const baseStyles = clsx(classNames?.base, className); const onNext = () => { - if (loop && activePage === (isRTL ? 1 : total)) { + if (loop && activePage === total) { return first(); } @@ -329,7 +324,7 @@ export function usePagination(originalProps: UsePaginationProps) { }; const onPrevious = () => { - if (loop && activePage === (isRTL ? total : 1)) { + if (loop && activePage === 1) { return last(); } diff --git a/packages/components/pagination/stories/pagination.stories.tsx b/packages/components/pagination/stories/pagination.stories.tsx index 39a0ae0571..7522778896 100644 --- a/packages/components/pagination/stories/pagination.stories.tsx +++ b/packages/components/pagination/stories/pagination.stories.tsx @@ -3,6 +3,7 @@ import {Meta} from "@storybook/react"; import {button, pagination} from "@heroui/theme"; import {cn} from "@heroui/theme"; import {ChevronIcon} from "@heroui/shared-icons"; +import {useLocale} from "@react-aria/i18n"; import {Pagination, PaginationItemRenderProps, PaginationItemType, usePagination} from "../src"; @@ -138,6 +139,10 @@ export const Controlled = () => { }; export const CustomItems = () => { + const {direction} = useLocale(); + + const isRTL = direction === "rtl"; + const renderItem = ({ ref, value, @@ -150,7 +155,7 @@ export const CustomItems = () => { if (value === PaginationItemType.NEXT) { return ( ); } @@ -158,7 +163,7 @@ export const CustomItems = () => { if (value === PaginationItemType.PREV) { return ( ); } @@ -217,6 +222,10 @@ export const CustomWithHooks = () => { boundaries: 10, }); + const {direction} = useLocale(); + + const isRTL = direction === "rtl"; + return (

Active page: {activePage}

@@ -226,7 +235,7 @@ export const CustomWithHooks = () => { return (
  • ); @@ -236,7 +245,7 @@ export const CustomWithHooks = () => { return (
  • ); diff --git a/packages/hooks/use-pagination/src/index.ts b/packages/hooks/use-pagination/src/index.ts index c45104e483..2c87a4eddc 100644 --- a/packages/hooks/use-pagination/src/index.ts +++ b/packages/hooks/use-pagination/src/index.ts @@ -85,17 +85,15 @@ export function usePagination(props: UsePaginationProps) { [total, activePage, onChangeActivePage], ); - const next = () => (isRTL ? setPage(activePage - 1) : setPage(activePage + 1)); - const previous = () => (isRTL ? setPage(activePage + 1) : setPage(activePage - 1)); - const first = () => (isRTL ? setPage(total) : setPage(1)); - const last = () => (isRTL ? setPage(1) : setPage(total)); + const next = () => setPage(activePage + 1); + const previous = () => setPage(activePage - 1); + const first = () => setPage(1); + const last = () => setPage(total); const formatRange = useCallback( (range: PaginationItemValue[]) => { if (showControls) { - return isRTL - ? [PaginationItemType.NEXT, ...range, PaginationItemType.PREV] - : [PaginationItemType.PREV, ...range, PaginationItemType.NEXT]; + return [PaginationItemType.PREV, ...range, PaginationItemType.NEXT]; } return range;