Skip to content
wdj

Pagination

Implemented Navigation

A page navigation component for navigating through paginated content.

Kumo reference: kumo-ui.com/components/pagination/

Presentation commands show demo feedback. Read the interaction guide to connect real actions.

Full Controls (Default)

The default pagination includes first, previous, page input, next, and last buttons.

Showing 1-10 of 100
Show template
{% load wdj %}
{% include "wdj/components/pagination.html" with page=1 per_page=10 total_count=100 controls="full" %}

Simple Controls

Use controls="simple" for a minimal pagination with only previous and next buttons.

Showing 1-10 of 100
Show template
{% load wdj %}
{% include "wdj/components/pagination.html" with page=1 per_page=10 total_count=100 controls="simple" %}

Unknown Totals

Use has_next_page when the data source does not return a total count. Common for cursor-based APIs where calculating the total is expensive.

Page 1
Show template
{% load wdj %}
{% include "wdj/components/pagination.html" with page=1 has_next_page=True text="Page 1" %}

Mid-Page State

Pagination in the middle of a dataset with all navigation enabled.

Showing 41-50 of 100
Show template
{% load wdj %}
{% include "wdj/components/pagination.html" with page=5 per_page=10 total_count=100 %}

Large Dataset

Pagination handles large datasets with many pages.

Showing 1-25 of 1250
Show template
{% load wdj %}
{% include "wdj/components/pagination.html" with page=1 per_page=25 total_count=1250 %}

Custom Text

You can set custom pagination text.

Page 1 - showing 25 per page
Show template
{% load wdj %}
{% include "wdj/components/pagination.html" with page=1 per_page=25 total_count=100 text="Page 1 - showing 25 per page" %}

Compound Components

For more control over layout and features, use the compound component API. This allows you to compose Pagination.Info, Pagination.PageSize, Pagination.Controls, and Pagination.Separator in any order.

Page Size Selector

Add a dropdown to let users select the number of items per page using compound subcomponents.

Showing 1-25 of 500
Per page:
25
Show template
{% load wdj %}
{% wdj_component "wdj/components/pagination.html" page=1 per_page=25 total_count=500 %}
  {% include "wdj/components/pagination_info.html" with page=1 per_page=25 total_count=500 only %}
  {% include "wdj/components/pagination_separator.html" only %}
  {% include "wdj/components/pagination_page_size.html" with value=25 only %}
  {% include "wdj/components/pagination_controls.html" with page=1 per_page=25 total_count=500 only %}
{% endwdj_component %}

Custom Page Size Options

Customize the available page size options with the options prop. Defaults to [25, 50, 100, 250].

Showing 1-10 of 200
Per page:
10
Show template
{% load wdj %}
{% wdj_component "wdj/components/pagination.html" page=1 per_page=10 total_count=200 %}
  {% include "wdj/components/pagination_info.html" with page=1 per_page=10 total_count=200 only %}
  {% include "wdj/components/pagination_separator.html" only %}
  {% include "wdj/components/pagination_page_size.html" with value=10 options=custom_page_sizes only %}
  {% include "wdj/components/pagination_controls.html" with page=1 per_page=10 total_count=200 only %}
{% endwdj_component %}

Custom Info Text

Use custom text to format the page and item counts.

Page 1 of 4
Show template
{% load wdj %}
{% wdj_component "wdj/components/pagination.html" page=1 per_page=25 total_count=100 text="Page 1 of 4" %}
  {% include "wdj/components/pagination_info.html" with text="Page 1 of 4" only %}
  {% include "wdj/components/pagination_controls.html" with page=1 per_page=25 total_count=100 only %}
{% endwdj_component %}

Custom Layout

Arrange components in any order. Here the page size selector is on the right.

Showing 1-25 of 500
Per page:
25
Show template
{% load wdj %}
{% wdj_component "wdj/components/pagination.html" page=1 per_page=25 total_count=500 %}
  {% include "wdj/components/pagination_info.html" with page=1 per_page=25 total_count=500 only %}
  <div class="flex flex-wrap items-center gap-2">
    {% include "wdj/components/pagination_controls.html" with page=1 per_page=25 total_count=500 only %}
    {% include "wdj/components/pagination_separator.html" only %}
    {% include "wdj/components/pagination_page_size.html" with value=25 only %}
  </div>
{% endwdj_component %}

Internationalization

Use the labels prop to customize all UI strings for different locales. All labels default to English.

Affichage de 1-10 sur 100
Show template
{% load wdj %}
{% wdj_component "wdj/components/pagination.html" page=1 per_page=10 total_count=100 %}
  <div aria-live="polite" aria-atomic="true" data-slot="pagination-info" data-wdj-i18n class="text-base text-kumo-subtle">
    Affichage de <span class="tabular-nums">1-10</span> sur <span class="tabular-nums">100</span>
  </div>
  {% include "wdj/components/pagination_controls.html" with page=1 per_page=10 total_count=100 labels=french_labels only %}
{% endwdj_component %}

API Reference

Prop Type Default Description
int 1 Current page number (1-indexed).
int 10 Number of items displayed per page.
int None Total number of items across all pages.
int None Total number of pages (derived from total_count / per_page if omitted).
bool None Whether another page exists when total count is unknown (cursor pagination).
"full" | "simple" "full" Controls mode: full (first, prev, input, next, last) or simple (prev, next).
"input" | "dropdown" "input" How page selector renders: text input or select dropdown.
str None Custom info string overriding "Showing X-Y of Z".
list[int] None Available page size choices, e.g. [10, 20, 50] or [25, 50, 100, 250].
int 25 Current selected page size.
str "Per page:" Label text displayed before the page size dropdown.
bool False Whether to place the page size selector on the right of controls.
dict {} Aria labels for internationalization (first_page, previous_page, next_page, last_page, page_number, page_size, navigation).
str None Base URL used to build anchor links for sequential navigation.
str "page" Query parameter name for current page.
str None HTMX target CSS selector for fragment swaps.
str "outerHTML" HTMX swap strategy.

Accessibility notes

Every interactive component keeps real semantics and keyboard support: native controls where possible, ARIA only where necessary, and a visible focus ring. See the Accessibility page for the shared contract.

Read the accessibility contract

Components

Components overview
AutocompleteFree-form input with local or HTMX-filtered suggestions.
BadgeSolid, tinted, outline and dot status labels.
BannerInline message bar with variants and optional action.
BreadcrumbsTrail navigation in two sizes.
ButtonVariants, sizes, shapes, icons and loading state.
ButtonGroupJoins a small set of tightly-coupled buttons into a single control (split buttons).
CheckboxSingle checkbox and indeterminate state.
ClipboardTextRead-only text field with a one-click copy-to-clipboard button.
Code / CodeHighlightedEscaped Pygments grammar highlighting, multiline tokens, line numbers, highlighted lines and localized copying.
CollapsibleComposable disclosure component for showing and hiding content.
Combobox / AutocompleteKumo-styled input/button triggers, search inside the popup, grouped local choices and debounced HTMX search.
CommandPaletteAccessible spotlight search overlay with Cmd+K keyboard shortcut.
DatePickerKumo-styled date and datetime popups; inline single, multiple and range calendars with bounds/presets.
DateRangePickerStyled popup or inline range calendar with bounds, presets and separately named form values.
DialogNative <dialog> modal with focus management.
DrawerEdge-anchored modal panel. LayerDialog has its own layered component.
DropdownMenuNative details menu with delegated keyboard navigation and dismissal.
EmptyEmpty-state placeholder with icon and action.
FieldLabel + description + error wrapper. Built into each control.
FlowDirected diagrams with branches, SVG connectors, custom anchors and responsive local scrolling.
GridResponsive CSS grid layout container with preset column configurations.
InlineCopyTextCompact borderless copy control for IDs and short values.
InputText field with label, description, leading/trailing icons.
InputAreaMulti-line textarea with auto-resize option.
InputGroupInput field with seamless prefix, suffix, and addon attachments.
LabelForm field label, optional marker and tooltip.
LayerCardCompound surface card with distinct primary and secondary layers.
LayerDialogLayered native modal with actions, forms, nested dialogs and pending states.
LinkInline, current and plain text links.
LoaderAnimated spinner in three sizes.
MenuBarCompact view selector using native radio semantics.
MeterProgress bar showing a measured value within a known range.
PaginationA page navigation component for navigating through paginated content.
PopoverAnchored popup with interactive content.
RadioRadio group, vertical and horizontal.
SelectKumo-styled Alpine dropdown with groups, rich options and multiple selection; native form values and fallback.
SensitiveInputPassword/secret input with reveal toggle and copy button.
SeparatorHorizontal / vertical rules with optional label.
SidebarRecursive navigation groups, account/zone views, search, loading, resize and full-screen mobile breadcrumbs.
SkeletonShimmer placeholder.
SliderInset single/range selection with vertical grips, value badges, endpoint labels and native keyboard/form behavior.
SurfaceBordered surface panel with header slot.
SwitchOn/off toggle in three sizes.
TableServer-driven table: sort, filter, select and paginate the full dataset.
Table of contentsPage section navigation tree with active link indicator.
TabsSegmented and underline tabs with a sliding indicator, responsive overflow and local Alpine or URL/HTMX state.
TagInputMulti-value badge input for tags and recipients.
TextHeading, body, secondary, success, error and mono text.
ToastyExpandable notification stack with variants, paused expiry and a live region.
ToolbarCompact grouped controls with shared borders, composed filters and keyboard arrow navigation.
TooltipHover and focus tooltip with grouped delays, Escape dismissal and viewport bounds.
↑ ↓ Navigate ↵ Select