Navigation

Pagination

<oblyx-pagination> renders a previous control, an indicator, and a next control, all real <a href> elements, not onclick-only buttons. It does not invent a routing scheme: the author supplies href-pattern, a URL template containing the literal token {page}, and this component substitutes it into every control's href. That makes plain navigation work with zero client JavaScript, keeps every page crawlable, and leaves HTMX free to progressively enhance the same anchors rather than being required for them to do anything at all.

Basic pagination

HTMLKotlin
<oblyx-pagination page="3" total-pages="8" href-pattern="?page={page}"></oblyx-pagination>
oblyxPagination(page = 3, totalPages = 8, hrefPattern = "?page={page}")

Deriving total pages from item count

Set total-items and page-size instead of total-pages and this component computes the page count itself. total-items takes precedence over total-pages when both are set.

Total pages from total-items

HTMLKotlin
<oblyx-pagination
  page="2"
  total-items="124"
  page-size="20"
  href-pattern="?page={page}"
></oblyx-pagination>
oblyxPagination(page = 2, totalItems = 124, pageSize = 20, hrefPattern = "?page={page}")

Indicator variant

pages (the default) renders page numbers with ellipsis collapsing once there are too many to show. count renders an "X to Y of Z" range and requires total-items. compact renders "Page X of Y". none renders only the previous/next controls.

Count variant

HTMLKotlin
<oblyx-pagination
  variant="count"
  page="2"
  total-items="124"
  page-size="20"
  href-pattern="?page={page}"
></oblyx-pagination>
oblyxPagination(
  variant = OblyxPaginationVariant.COUNT,
  page = 2,
  totalItems = 124,
  pageSize = 20,
  hrefPattern = "?page={page}",
)

Compact variant

HTMLKotlin
<oblyx-pagination
  variant="compact"
  page="4"
  total-pages="10"
  href-pattern="?page={page}"
></oblyx-pagination>
oblyxPagination(
  variant = OblyxPaginationVariant.COMPACT,
  page = 4,
  totalPages = 10,
  hrefPattern = "?page={page}",
)

No indicator

HTMLKotlin
<oblyx-pagination variant="none" page="3" total-pages="8" href-pattern="?page={page}"></oblyx-pagination>
oblyxPagination(
  variant = OblyxPaginationVariant.NONE,
  page = 3,
  totalPages = 8,
  hrefPattern = "?page={page}",
)

Size

Small pagination

HTMLKotlin
<oblyx-pagination size="sm" page="3" total-pages="8" href-pattern="?page={page}"></oblyx-pagination>
oblyxPagination(size = OblyxPaginationSize.SM, page = 3, totalPages = 8, hrefPattern = "?page={page}")

Disabled

disabled omits href from every control, regardless of page bounds.

Disabled pagination

HTMLKotlin
<oblyx-pagination disabled page="3" total-pages="8" href-pattern="?page={page}"></oblyx-pagination>
oblyxPagination(disabled = true, page = 3, totalPages = 8, hrefPattern = "?page={page}")

No href-pattern

Without href-pattern, every control still renders, inert, with no href and aria-disabled="true", rather than a dead link to nowhere. This is the state a page renders in before its pagination destination is wired up.

No href-pattern set

Every control is present but inert.

HTMLKotlin
<oblyx-pagination page="3" total-pages="8"></oblyx-pagination>
oblyxPagination(page = 3, totalPages = 8)

Driving an HTMX swap

Because every control is a real anchor, HTMX enhances it the same way it enhances any other link: add hx-boost (or hx-get/hx-target per control) to <oblyx-pagination> itself and HTMX picks up the real <a> elements it renders into its light DOM. Nothing about this component changes to support it: the anchors it already renders for plain navigation are the same anchors HTMX boosts.

hx-boost on the pagination host

This page does not load htmx.js, so the hx-* attributes here are inert markup: clicking a control does a normal same-page navigation via its real href, exactly the progressive-enhancement fallback HTMX is designed around.

Results for page 3.
HTMLKotlin
<oblyx-pagination
  page="3"
  total-pages="8"
  href-pattern="?page={page}"
  hx-boost="true"
  hx-target="#pagination-htmx-target"
  hx-select="#pagination-htmx-target"
></oblyx-pagination>
<div id="pagination-htmx-target">Results for page 3.</div>
oblyxPagination(page = 3, totalPages = 8, hrefPattern = "?page={page}") {
  attributes["hx-boost"] = "true"
  attributes["hx-target"] = "#results"
  attributes["hx-select"] = "#results"
}

Reference

<oblyx-pagination>

AttributeTypeDefaultDescription
pagenumber1Current page, 1-based.
total-pagesnumber | undefinedTotal known page count. Ignored when total-items is also set. See computedTotalPages. Unset means "unknown total" (e.g. a cursor-based listing): the pages/count/compact indicators all need a known total to render anything meaningful, so an unset total degrades to prev/next-only rather than guessing.
total-itemsnumber | undefinedTotal item count. Takes precedence over total-pages when both are set, and is required for variant="count"'s "X to Y of Z" text.
page-sizenumber10Items per page, used to derive total pages from total-items.
href-patternstring | undefinedURL template for every page control's href, containing the literal token {page}. Unset renders every control inert rather than guessing a routing scheme.
variantpagescountcompactnonepagesIndicator style between the prev/next controls. dots and input are not implemented.
sibling-countnumber1Pages shown on each side of the current page. pages variant only.
stepnumber1Prev/next stride. Clamped to a minimum of 1.
sizesmmdmdControl height.
disabledbooleanfalseDisables every control, regardless of page bounds.
labelstring | undefinedPagination<nav> landmark accessible name.