@fiscozen/pagination
v1.0.1
Published
Design System Pagination component
Keywords
Readme
@fiscozen/pagination
For usage documentation, see Storybook Documentation
Development
Setup
pnpm install
pnpm --filter @fiscozen/pagination buildArchitecture
The package is split into two layers:
usePaginationcomposable (src/usePagination.ts): Pure logic that builds a reactive list ofPaginationItemobjects fromcurrentPage,totalPages, andPaginationOptions. AcceptsMaybeRefOrGetterinputs so it works with refs, computed values, and getter functions.FzPaginationcomponent (src/FzPagination.vue): Thin UI wrapper that maps items toFzButton/FzIconButton/FzIconcomponents and emitsupdate:currentPageon click.
Code Organization
src/
index.ts Main exports (component, composable, types)
types.ts All public types (FzPaginationProps, PaginationOptions, PaginationItem, etc.)
usePagination.ts Composable: token generation, clamping, ellipsis filtering
FzPagination.vue Component: renders items, handles v-model
__tests__/
FzPagination.spec.ts Component unit tests
usePagination.spec.ts Composable unit testsKey Concepts
Token Pipeline
usePagination builds page items through a pipeline:
- Clamp current page into
[1, totalPages] - Slot config determines how many center pages, anchors, and ellipsis slots are available based on
PaginationOptions - Token generation creates a compact list of page numbers and
'ellipsis'markers that fits the slot budget - Ellipsis filtering drops or keeps ellipsis based on the configured visibility (
none,both,before,after) - Normalization removes redundant ellipsis (adjacent duplicates, gaps of 1)
- Item mapping converts tokens into
PaginationItemobjects withtype,value,label,current,disabled
Position / Alignment
The position prop maps to a justifyClass computed that applies Tailwind justify-start, justify-center, or justify-end to FzContainer. Default is 'end'.
Responsive Behaviour
The component uses useMediaQuery from @fiscozen/composables to detect desktop vs mobile. On mobile, prev/next buttons render as icon-only (FzIconButton) wrapped in <span> elements with flex layout classes.
buttonClasses Helper
buttonClasses(item) centralizes all conditional CSS classes for each pagination item:
!min-w-44on every itemflex-1+justify-start/justify-endfor prev/next on mobilefz-pagination-disable-truncateon the current page button
Truncate Override (Scoped CSS)
FzButton applies a .truncate class internally. The scoped CSS rule :deep(.fz-pagination-disable-truncate > .truncate) overrides overflow, text-overflow, and white-space on the active page button so long labels remain visible.
Testing
Running Tests
pnpm --filter @fiscozen/pagination test:unit
pnpm --filter @fiscozen/pagination coverageTest Structure
Tests mock window.matchMedia (required by useMediaQuery) in beforeEach. They query the DOM directly with wrapper.findAll('button') rather than component name lookups for resilience against component renaming.
Coverage target: >90% line coverage.
Adding Features
- Update types in
src/types.ts(add props or options fields with JSDoc) - Update composable in
src/usePagination.tsif the feature affects item generation logic - Update component in
src/FzPagination.vuefor template/rendering changes - Add tests in
src/__tests__/FzPagination.spec.ts - Update stories in
apps/storybook/src/stories/navigation/Pagination.stories.ts - Update MDX in
apps/storybook/src/FzPagination.mdx
Dependencies
@fiscozen/button-FzButtonandFzIconButtonfor page controls@fiscozen/container-FzContainerfor layout@fiscozen/icons-FzIconfor ellipsis indicator@fiscozen/composables-useMediaQueryfor responsive layout@fiscozen/style-breakpointsfor media query thresholds
Build
pnpm --filter @fiscozen/pagination buildRuns vue-tsc for type checking followed by Vite library build. Output goes to dist/.
