kovax-react 0.6: Pagination, breakpoint hooks, and one source of truth for responsive layout

kovax-react 0.6 is on npm. If you already use kovax-react 0.5 with ThemeProvider and CSS-variable theming, this release is the “admin panel polish” follow-up: a pagination component you can drop next to tables and search results, plus responsive hooks that read the same breakpoint.* tokens as themeToken and your stylesheets — no duplicate 768px constants in JS.

TL;DR

Area What shipped
Pagination Semantic nav, prev/next, numbered pages, ellipsis windows, aria-current="page", motion from duration.* / easing.*, honors prefers-reduced-motion
Tree-shaking Optional kovax-react/pagination entry exports Pagination + getPaginationItems
Responsive useMediaQuery, useBreakpointUp, breakpointMinMediaQuery, breakpointMinWidth, breakpointMinMediaQueryFromToken — all aligned with breakpoints (sm2xl in em)
Docs Pagination.md, playground Components → Pagination, Documentation topic with EN/RU UI copy

No new runtime peer dependencies beyond what you already use for kovax-react.

Install

npm install kovax-react@0.6.0

Wrap your app in ThemeProvider as before — Pagination and the media-query hooks pick up the same CSS variables and token scale as the rest of the library.

Why another minor release?

After 0.5, two gaps showed up in real apps:

  1. Lists and tables need a pager — not just “page 3 of 40” text, but keyboard-friendly controls, clear current-page state, and ellipsis when there are dozens of pages.
  2. Breakpoints were defined twice — once in design tokens / CSS, again as magic numbers in React. That drifts the moment someone tweaks breakpoint.md.

0.6 closes both without pulling in a routing or data-fetching layer: you keep page / pageCount controlled in parent state (or your router) and wire onPageChange.

Pagination

Basics

import { Pagination } from "kovax-react";
import { useState } from "react";

export function SearchResultsPager() {
  const [page, setPage] = useState(1);

  return (
    <Pagination
      page={page}
      pageCount={40}
      onPageChange={setPage}
      variant="outline"
      size="sm"
      aria-label="Search results"
    />
  );
}

Props worth knowing:

  • variant: soft (default) or outline
  • size: sm | md
  • siblingCount: how many page numbers sit beside the current page (default 1); increase for wider “windows” on dense UIs
  • disabled: freeze controls while a request is in flight
  • i18n: previousAriaLabel, nextAriaLabel, getPageAriaLabel, optional visible previousLabel / nextLabel
<Pagination
  page={page}
  pageCount={12}
  onPageChange={setPage}
  siblingCount={2}
  previousAriaLabel="Previous"
  nextAriaLabel="Next"
  getPageAriaLabel={(p) => `Page ${p}`}
/>

The component renders nothing when pageCount < 1, so you can skip conditional JSX around empty result sets.

Accessibility and motion

  • Root is a nav with your aria-label (required for a meaningful landmark).
  • Active page uses aria-current="page".
  • Ellipsis markers are aria-hidden; navigation stays on real buttons.
  • Hover/active feedback uses theme motion tokens; when the user prefers reduced motion, scale animations are skipped.

Custom layout, same gap logic

Need your own button components or a mobile-specific strip? Export the algorithm:

import { getPaginationItems } from "kovax-react/pagination";

const items = getPaginationItems(page, pageCount, 1);
// → (number | "ellipsis")[]

return (
  <nav aria-label="Results">
    {items.map((item, i) =>
      item === "ellipsis" ? (
        <span key={`e-${i}`} aria-hidden>span>
      ) : (
        <button
          key={item}
          type="button"
          aria-current={item === page ? "page" : undefined}
          onClick={() => setPage(item)}
        >
          {item}
        button>
      ),
    )}
  nav>
);

Smaller bundles

Full barrel:

import { Pagination, getPaginationItems } from "kovax-react";

Pagination-only entry (same API, less to parse if you only ship a pager):

import { Pagination, getPaginationItems } from "kovax-react/pagination";

Full prop reference: Pagination.md.

Breakpoints in JavaScript

Design tokens already expose em breakpoints (sm 30em, md 48em, lg 62em, …). They respect root font size — a nicer default than hard-coded pixels for accessibility.

Hooks and helpers:

API Role
useBreakpointUp("md") true when viewport ≥ token md
useMediaQuery(query, options?) Generic matchMedia subscription
breakpointMinMediaQuery("md") "(min-width: 48em)" string for CSS-in-JS or tests
breakpointMinWidth("md") Raw token value (48em)
breakpointMinMediaQueryFromToken("breakpoint.md") Same as above via themeToken path
import {
  useBreakpointUp,
  useMediaQuery,
  breakpointMinMediaQuery,
  themeToken,
} from "kovax-react";

const isMdUp = useBreakpointUp("md");
const isWide = useMediaQuery(`(min-width: ${themeToken("breakpoint.lg")})`);
const mqForCss = breakpointMinMediaQuery("md"); // "(min-width: 48em)"

SSR and hydration

useMediaQuery is built on useSyncExternalStore, so server and first client paint can agree via defaultMatches:

// Desktop-first layout: fewer “flash from mobile to desktop” warnings
const isLgUp = useBreakpointUp("lg", { defaultMatches: true });

On the server, getServerSnapshot returns defaultMatches (default false). After hydration, the real matchMedia result takes over and listeners update on resize.

Token docs (including breakpoint table): Tokens.md.

Example: responsive columns without duplicating constants

import { Grid, useBreakpointUp } from "kovax-react";

export function ProductGrid({ children }: { children: React.ReactNode }) {
  const threeCols = useBreakpointUp("lg");

  return (
    <Grid columns={threeCols ? 3 : 1} gap={16}>
      {children}
    Grid>
  );
}

Try it in the playground

The live site is still statically prerendered (SEO-friendly routes, sitemap). For 0.6, open:

  • Components → Pagination — variants, sizes, ellipsis, disabled state, code tabs
  • Components → Design tokens — breakpoint scale next to spacing, motion, z-index
  • Documentation → Pagination — the same Markdown as the repo, with EN/RU chrome

No local install required to click through examples.

Changelog and what’s next

Full release notes (including a Russian summary block): CHANGELOG.md.

From the 0.5 roadmap, items still on the radar include Breadcrumb, richer Toast patterns, and more overlay polish. Menu already exists on the Popover primitives in the current tree — feedback on API shape is welcome.

If something’s missing, open an issue or PR — or leave a comment here; I read them.

Thanks for reading — happy paging.

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post

Upcoming Events – May 2026

Next Post

Your Equipment Passed Calibration. So Why Are Results Still Questioned?

Related Posts