Pagination

Facilitates navigation between pages.

...

Showing 0 - 10

	<script lang="ts">
  import { Pagination } from "bits-ui";
  import CaretLeft from "phosphor-svelte/lib/CaretLeft";
  import CaretRight from "phosphor-svelte/lib/CaretRight";
</script>
 
<Pagination.Root count={100} perPage={10}>
  {#snippet children({ pages, range })}
    <div class="my-8 flex items-center">
      <Pagination.PrevButton
        class="mr-[25px] inline-flex size-10 items-center justify-center rounded-[9px] bg-transparent hover:bg-dark-10 active:scale-98 disabled:cursor-not-allowed disabled:text-muted-foreground hover:disabled:bg-transparent"
      >
        <CaretLeft class="size-6" />
      </Pagination.PrevButton>
      <div class="flex items-center gap-2.5">
        {#each pages as page (page.key)}
          {#if page.type === "ellipsis"}
            <div class="text-[15px] font-medium text-foreground-alt">...</div>
          {:else}
            <Pagination.Page
              {page}
              class="inline-flex size-10 items-center justify-center rounded-[9px] bg-transparent text-[15px] font-medium hover:bg-dark-10 active:scale-98 disabled:cursor-not-allowed disabled:opacity-50 hover:disabled:bg-transparent data-[selected]:bg-foreground data-[selected]:text-background"
            >
              {page.value}
            </Pagination.Page>
          {/if}
        {/each}
      </div>
      <Pagination.NextButton
        class="ml-[29px] inline-flex size-10 items-center justify-center rounded-[9px] bg-transparent hover:bg-dark-10 active:scale-98 disabled:cursor-not-allowed disabled:text-muted-foreground hover:disabled:bg-transparent"
      >
        <CaretRight class="size-6" />
      </Pagination.NextButton>
    </div>
    <p class="text-center text-[13px] text-muted-foreground">
      Showing {range.start} - {range.end}
    </p>
  {/snippet}
</Pagination.Root>

Structure

	<script lang="ts">
	import { Pagination } from "bits-ui";
</script>
 
<Pagination.Root let:pages>
	<Pagination.PrevButton />
	{#each pages as page (page.key)}
		<Pagination.Page {page} />
	{/each}
	<Pagination.NextButton />
</Pagination.Root>

Managing Page State

Bits UI offers several approaches to manage and synchronize the Pagination's page state, catering to different levels of control and integration needs.

1. Two-Way Binding

For seamless state synchronization, use Svelte's bind:page directive. This method automatically keeps your local state in sync with the component's internal state.

	<script lang="ts">
	import { Pagination } from "bits-ui";
	let myPage = $state(1);
</script>
 
<button onclick={() => (myPage = 2)}> Go to page 2 </button>
 
<Pagination.Root bind:pressed={myPage}>
	<!-- ...-->
</Pagination.Root>

Key Benefits

  • Simplifies state management
  • Automatically updates myPage when the internal state changes (e.g., via clicking on a page button)
  • Allows external control (e.g., changing the page via a separate button/programmatically)

2. Change Handler

For more granular control or to perform additional logic on state changes, use the onPageChange prop. This approach is useful when you need to execute custom logic alongside state updates.

	<script lang="ts">
	import { Pagination } from "bits-ui";
	let myPage = $state(1);
</script>
 
<Pagination.Root
	checked={myPage}
	onPressedChange={(p) => {
		myPage = p;
		// additional logic here.
	}}
>
	<!-- ... -->
</Pagination.Root>

Use Cases

  • Implementing custom behaviors on page change
  • Integrating with external state management solutions
  • Triggering side effects (e.g., logging, data fetching)

3. Fully Controlled

For complete control over the component's pressed state, use the controlledPage prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events.

To implement controlled state:

  1. Set the controlledPage prop to true on the Pagination.Root component.
  2. Provide a page prop to Pagination.Root, which should be a variable holding the current state.
  3. Implement an onPageChange handler to update the state when the internal state changes.
	<script lang="ts">
	import { Pagination } from "bits-ui";
	let myPage = $state(1);
</script>
 
<Pagination.Root controlledPage page={myPage} onPageChange={(p) => (myPage = p)}>
	<!-- ... -->
</Pagination.Root>

When to Use

  • Implementing complex logic
  • Coordinating multiple UI elements
  • Debugging state-related issues

Ellipsis

The pages snippet prop consists of two types of items: 'page' and 'ellipsis'. The 'page' type represents an actual page number, while the 'ellipsis' type represents a placeholder for rendering an ellipsis between pages.

API Reference

Pagination.Root

The root pagination component which contains all other pagination components.

Property Type Description
count required
number

The total number of items.

Default: undefined
page $bindable
number

The selected page. You can bind this to a variable to control the selected page from outside the component.

Default: undefined
onPageChange
function

A function called when the selected page changes.

Default: undefined
controlledPage
boolean

Whether or not the page state is controlled or not. If true, the component will not update the page state internally, instead it will call onPageChange when it would have otherwise, and it is up to you to update the page prop that is passed to the component.

Default: false
perPage
number

The number of items per page.

Default: 1
siblingCount
number

The number of page triggers to show on either side of the current page.

Default: 1
loop
boolean

Whether or not the pagination should loop through the items when reaching the end while navigating with the keyboard.

Default: false
orientation
enum

The orientation of the pagination. This determins how keyboard navigation will work with the component.

Default: horizontal
ref $bindable
HTMLDivElement

The underlying DOM element being rendered. You can bind to this to get a reference to the element.

Default: undefined
children
Snippet

The children content to render.

Default: undefined
child
Snippet

Use render delegation to render your own element. See delegation docs for more information.

Default: undefined

Pagination.Page

A button that triggers a page change.

Property Type Description
page
PageItem

The page item this component represents.

Default: undefined
ref $bindable
HTMLButtonElement

The underlying DOM element being rendered. You can bind to this to get a reference to the element.

Default: undefined
children
Snippet

The children content to render.

Default: undefined
child
Snippet

Use render delegation to render your own element. See delegation docs for more information.

Default: undefined
Data Attribute Value Description
data-selected
''

Present on the current page element.

data-pagination-page
''

Present on the page trigger element.

Pagination.PrevButton

The previous button of the pagination.

Property Type Description
ref $bindable
HTMLButtonElement

The underlying DOM element being rendered. You can bind to this to get a reference to the element.

Default: undefined
children
Snippet

The children content to render.

Default: undefined
child
Snippet

Use render delegation to render your own element. See delegation docs for more information.

Default: undefined
Data Attribute Value Description
data-pagination-prev-button
''

Present on the previous button element.

Pagination.NextButton

The next button of the pagination.

Property Type Description
ref $bindable
HTMLButtonElement

The underlying DOM element being rendered. You can bind to this to get a reference to the element.

Default: undefined
children
Snippet

The children content to render.

Default: undefined
child
Snippet

Use render delegation to render your own element. See delegation docs for more information.

Default: undefined
Data Attribute Value Description
data-pagination-next-button
''

Present on the next button element.