Pagination: an explicit `disabled` for the whole pagination (feature request)

Open
#522 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
25/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Active
Tech stack
typescript

Research direction

Start with the Pagination root and its page, step and ellipsis parts, and the click handler that already cancels presses on a step at its end; that is the pattern a disabled option should extend. Reproduce the bug with the Solid example: Enter on a page marked aria-disabled still calls onPageChange. Done means a disabled root or part blocks keyboard, click, href and auxclick, the state exposes disabled, and the tabindex and controller behaviour are documented. The maintainer has left those choices open, so confirm them first.

Written by the indexing model from the issue text.

Description

What I'd like

A disabled prop on Pagination (and, ideally, on each part) that turns the pagination off
as a unit, the way a disabled form control is off: while a list is loading, or while a filter
the pages depend on is being edited.

Today there is no such option, and the attribute an app would reach for does not do it: a part
the app marks aria-disabled="true" looks disabled to assistive technology but still pages
when it is pressed.

Expected behaviour

With disabled on the root (or on one part, for that part only):

  • Keyboard: each page and step says aria-disabled="true" and carries data-disabled, as
    a step at its end does today. Enter and Space on it do nothing and onPageChange is not
    called. Whether disabled parts leave the tab order (tabindex="-1") or stay focusable as the
    end steps do is your call; please document it either way.
  • getHref: a disabled part rendered as a link does not navigate. Its href is removed,
    as for a step at its end, so a plain click, a modified click (Ctrl/Cmd, Shift) and a middle
    click open nothing.
  • Router render: the pagination's click handler calls preventDefault() on a disabled
    part before the router link sees the click (as it does for a step at its end), so a router
    Link leaves it alone; the same for auxclick, so a middle click opens no tab.
  • Controller calls: setPage, next, previous, first and last on a
    createPaginationController() controller are either ignored while disabled or still page
    (an app may want to move a disabled pager programmatically). Please pick one and document
    it; I'd expect them to still work, since the app owns the controller.
  • State: the render functions' state carries disabled for every part, so an app can
    style a disabled page as it styles a disabled step.
Today: aria-disabled on a page does not stop it

@ui-sdk/[email protected], solid-js / @solidjs/web 2.0.0-rc.21, development server
and production build alike.

import {
	Pagination,
	PaginationEllipsis,
	PaginationItem,
	PaginationLink,
	PaginationList,
} from '@ui-sdk/solid/pagination'
import { createSignal, For } from 'solid-js'

export function App() {
	const [page, setPage] = createSignal(1)
	return (
		<>
			<Pagination
				aria-label="Pagination"
				pageCount={10}
				page={page()}
				onPageChange={(next) => setPage(next)}
			>
				<PaginationList>
					{({ items }) => (
						<For each={items}>
							{(item) => (
								<PaginationItem>
									{typeof item === 'number' ? (
										<PaginationLink page={item} aria-disabled="true" />
									) : (
										<PaginationEllipsis />
									)}
								</PaginationItem>
							)}
						</For>
					)}
				</PaginationList>
			</Pagination>
			<output>{page()}</output>
		</>
	)
}
  1. Tab to page 2 (it is focusable and announced as dimmed/unavailable).
  2. Press Enter.

Expected (with a disabled option): the page stays 1. Actual: the page becomes 2, the
output reads 2 and page 2 gets aria-current="page". The same happens on Space and on a
click that reaches it.

Workaround

The app cancels the press itself: an onClick (and onAuxClick, for links) on each part
that calls preventDefault(), which the pagination honours, or details.cancel() in
onPageChange. Both work, but every app has to know to do it, and to repeat it on each part
and on auxclick for links.


Reproduced on @ui-sdk/core / @ui-sdk/solid 0.1.0-beta.2.

Dominant language
TypeScript
Stars
4.4k
Forks
122
Avg merge
3h 12m
Merged PRs (30d)
437

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from vercel-labs/ui

All issues in vercel-labs/ui

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.