CursorPagination

Table & List

Relay connection 목록을 위한 커서 기반 페이지네이션.

Usage

GraphQL connection처럼 페이지 번호 대신 커서로 앞/뒤 이동하는 목록을 넘길 때

import

import

import { CursorPagination } from '@mildang/design-system/unofficial/CursorPagination';

예제를 복사해 쓸 때 필요한 준비

@mildang/styled-system 은 이 저장소에서 Panda 가 생성하는 산출물이다. 저장소 안에서는 turbo run ship 이후 쓸 수 있고, 패키지 소비자는 자기 Panda 산출물이나 다른 레이아웃 수단으로 바꿔야 한다.

API Reference

CursorPagination Props

Prop

Type

Default

onFirstPage
필수

() => void

지정 안 함

onLastPage
필수

() => void

지정 안 함

onNextPage
필수

(cursor: string) => void

지정 안 함

onPreviousPage
필수

(cursor: string) => void

지정 안 함

loading

boolean

false

onPageSizeChange

(pageSize: number) => void

지정 안 함

pageInfo

CursorPageInfo

지정 안 함

pageSize

number

지정 안 함

pageSizeOptions

readonly number[]

[10, 20, 30, 40, 50] as const

selectStartAdornment

ReactNode

지정 안 함

예제

기본 사용

이전/다음 페이지 이동과 페이지 크기 Select 를 함께 제공하는 기본형입니다.

import type { ComponentProps } from 'react';

import { CursorPagination, type CursorPaginationProps } from '@mildang/design-system/unofficial/CursorPagination';
import { useState } from 'react';
import { css } from '@mildang/styled-system/css';

const ControlledCursorPagination = (args: CursorPaginationProps) => {
  const [page, setPage] = useState(2);
  const [pageSize, setPageSize] = useState(args.pageSize);

  return (
    <div className={css({ display: 'grid', gap: '12' })}>
      <output aria-live="polite">현재 페이지: {page}</output>
      <CursorPagination
        {...args}
        pageSize={pageSize}
        pageInfo={{
          hasPreviousPage: page > 1,
          hasNextPage: page < 5,
          startCursor: `start-${page}`,
          endCursor: `end-${page}`,
        }}
        onPageSizeChange={setPageSize}
        onFirstPage={() => setPage(1)}
        onPreviousPage={() => setPage((current) => Math.max(1, current - 1))}
        onNextPage={() => setPage((current) => Math.min(5, current + 1))}
        onLastPage={() => setPage(5)}
      />
    </div>
  );
};

// story 캔버스 100% 를 차지하도록 wrapper 로 폭을 채운다. 컨테이너 쿼리는 wrapper 폭에 반응.
const fullWidthStyle = css({ width: '100%', p: '16' });

const noopArgs = {
  onFirstPage: () => {},
  onPreviousPage: () => {},
  onNextPage: () => {},
  onLastPage: () => {},
};

const STORY_DEFAULT_ARGS = { ...({}), ...({
    ...noopArgs,
    pageSize: 20,
    onPageSizeChange: () => {},
  }) } as ComponentProps<typeof ControlledCursorPagination>;

const CursorPaginationBasicExampleRender = (args: ComponentProps<typeof ControlledCursorPagination>) => (
    <div className={fullWidthStyle}>
      <ControlledCursorPagination {...args} />
    </div>
  );

export default function CursorPaginationBasicExample(props: Partial<ComponentProps<typeof ControlledCursorPagination>>) {
  const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof ControlledCursorPagination>;
  return CursorPaginationBasicExampleRender(mergedProps);
}

페이지 크기 없음

pageSize·onPageSizeChange 를 넘기지 않으면 Select 가 자동으로 숨겨지고 이동 버튼만 가운데 정렬됩니다.

import type { ComponentProps } from 'react';

import { useState } from 'react';
import { CursorPagination } from '@mildang/design-system/unofficial/CursorPagination';
import { css } from '@mildang/styled-system/css';

// story 캔버스 100% 를 차지하도록 wrapper 로 폭을 채운다. 컨테이너 쿼리는 wrapper 폭에 반응.
const fullWidthStyle = css({ width: '100%', p: '16' });

const noopArgs = {
  onFirstPage: () => {},
  onPreviousPage: () => {},
  onNextPage: () => {},
  onLastPage: () => {},
};

const STORY_DEFAULT_ARGS = { ...({}), ...(noopArgs) } as ComponentProps<typeof CursorPagination>;

const CursorPaginationWithoutPageSizeExampleRender = (args: ComponentProps<typeof CursorPagination>) => {
    const [page, setPage] = useState(2);
    return (
      <div className={fullWidthStyle}>
        <output aria-live="polite">현재 페이지: {page}</output>
        <CursorPagination
          {...args}
          pageInfo={{
            hasPreviousPage: page > 1,
            hasNextPage: page < 5,
            startCursor: `start-${page}`,
            endCursor: `end-${page}`,
          }}
          onFirstPage={() => setPage(1)}
          onPreviousPage={() => setPage((current) => Math.max(1, current - 1))}
          onNextPage={() => setPage((current) => Math.min(5, current + 1))}
          onLastPage={() => setPage(5)}
        />
      </div>
    );
  };

export default function CursorPaginationWithoutPageSizeExample(props: Partial<ComponentProps<typeof CursorPagination>>) {
  const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof CursorPagination>;
  return CursorPaginationWithoutPageSizeExampleRender(mergedProps);
}