refactor(pagination): one shared Pagination component for all six surfaces#477
Open
rusikv wants to merge 1 commit into
Open
refactor(pagination): one shared Pagination component for all six surfaces#477rusikv wants to merge 1 commit into
rusikv wants to merge 1 commit into
Conversation
Six surfaces each carried their own pagination: IoT Hub's link-based PaginationLink + runtime updater, a button shell shared by Device Library and Partners (with the windowing JS copy-pasted into both), and bespoke innerHTML renderers on the blog and case-studies indexes. Three drifted copies of the windowing algorithm, four styling vocabularies, and recurring a11y gaps. Replace all of it with src/components/Pagination/: - Pagination.astro — one nav, two modes: basePath renders real anchors (SSG, rel=prev/next, crawlable); without it, buttons that dispatch bubbling tb-pagination:page-change events. Numbered list on desktop, compact 'Page X of Y' row below lg. Brand tokens (indigo/lavender current-page pill), aria-current in both modes, focus-visible rings. - pagination-client.ts — updatePagination() rebuilds the lists for client-driven surfaces; restores keyboard focus to the equivalent control after each rebuild (fixes a focus-loss bug all the old implementations shared). - pagination-shared.ts — the single windowing algorithm + strings. - PerPageSelector.astro — the IoT-Hub-only items-per-page dropdown, composed in via the 'controls' slot from consumer files so its script/styles ship only to IoT Hub pages (Astro bundles per import graph, not per render). Consumers keep what is theirs: URL state (?page= on blog), scroll behavior, sessionStorage restore (case-studies), and the dynamic search pipeline (IoT Hub) — the component only renders and reports. Intended deltas: unified look on all surfaces, blog gains prev/next chevrons, grid surfaces show full number rows up to 7 pages (was 5), Device Library/Partners drop the redundant always-visible 'Page X of Y' line (lives in the sub-lg compact layout now).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Extracts pagination into a single shared component —
src/components/Pagination/— and migrates every surface that paginates to it:PaginationLink+PaginationChevron+iot-hub-pagination-update.tsinnerHTMLrenderer,cs-*classesinnerHTMLrenderer (no prev/next)Net: −389 lines, one windowing algorithm instead of three drifted copies, one styling vocabulary instead of four.
Design
basePath, page numbers are real anchors (/iot-hub/widgets/3/,rel=prev/next, crawlable, zero JS). Without it, buttons dispatch bubblingtb-pagination:page-changeevents andupdatePagination()rebuilds the nav. IoT Hub uses both in sequence: static links until search/filters activate the dynamic pipeline.?page=), scroll handling, sessionStorage restore (case-studies), API refetching (IoT Hub) all stay in consumer code — the component only renders and reports. This boundary is documented in a design-contract comment at the top of the component.controlsslot (PerPageSelector.astro, the items-per-page dropdown). Slotting instead of a prop keeps the dropdown's script/styles out of the other surfaces' bundles — Astro bundles per import graph, not per render.Improvements over the old implementations
<body>; the old case-studies code could even double-fire prev/next).aria-current="page"everywhere (previously IoT Hub only); icon buttons have aria-labels at all widths;prefers-reduced-motionrespected.--color-brand/-contrast) replace hardcoded#b3c7ff/#17181c/--sl-*colors → correct dark theme on all surfaces.lgbreakpoint on every surface.Intended visual/behavior deltas (not regressions)
lglayout shows it).Verification
astro check(0/0/0), ESLint clean on all touched files./blog/?page=2exercises the client updater + URL restore end-to-end.lint:linkchecknot yet run (no routes/links changed by this PR — pagination URLs are generated by the samepaginate()/getStaticPathscode as before).