Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use links for pagination #945

Closed
jasongitmail opened this issue Mar 24, 2024 · 4 comments
Closed

Use links for pagination #945

jasongitmail opened this issue Mar 24, 2024 · 4 comments
Labels
type: feature Introduction of new functionality to the application

Comments

@jasongitmail
Copy link
Contributor

jasongitmail commented Mar 24, 2024

Describe the feature

My understanding is the pagination element uses onPageChange() to programmatically navigate.

This creates downsides related to progressive enhancement (links won't work for SSR'd pages when user has JS disabled), SEO (b/c no anchor elements for a crawler to follow), and potentially speed (but I haven't confirmed if SvelteKit preloads destination pages, b/c I decided to keep my custom pagination element for now for the reasons described here).

An alternate approach could be to:

  1. Use a elements for the page links.
  2. Allow the component to accept a property representing a function that specifies how to format the href values. Then you can use this to build the href values and it's a simpler DX than needing to import the correct function to programmatically navigate and write code for this. E.g.
href=((page: number) => `/blog/${page}`}

The caveat is that the current callback may be more flexible for something like in-page tables, but you could argue the dev should be updating the URL state and that nudges them in the right direction. Or alternatively, onPageChange() could be retained as a fallback if the href prop is not specified, although this brings some added implementation complexity.

(Will let you transfer the issue to Bits UI if you prefer it to live there.)

@jasongitmail jasongitmail added the type: feature Introduction of new functionality to the application label Mar 24, 2024
@huntabyte
Copy link
Owner

Hey Jason, you should be able to use the asChild prop and render a link to get the behavior you would expect. You are correct in that the reason it doesn't use it by default as there are a number of use cases for pagination.

@huntabyte huntabyte closed this as not planned Won't fix, can't repro, duplicate, stale Mar 25, 2024
@jasongitmail
Copy link
Contributor Author

An example would be helpful in the docs since this will be a very common need for pagination, but its not clear about how to currently

@matrs
Copy link

matrs commented Nov 13, 2024

I think the main use case for pagination does need links. Also, there are so many packages for tables/tabular data, with pagination included, which seems to be the most popular use case for pagination which doesn't need links. I second @jasongitmail on this, it would be nice to have full examples, for me it's been very hard to use it without a single full example anywhere (google doesn't have a single one).

@while1618
Copy link

Have you been able to find a working solution for this? I was looking through a documentation and issues on shadcn-svelte and bits-ui, but I couldn't find anything useful.

I tried to use children or child snippet on Pagination.PrevButton, Pagination.NextButton and Pagination.Link but nothing seems to work like it should, I either get click registered twice, one is default behavior and other is link that I added, or I lose some default behavior like disabled next/previous button on end of the list.

This is my best try:

<Pagination.Root {page} {count} perPage={size}>
  {#snippet children({ pages, currentPage })}
    <Pagination.Content>
      <Pagination.Item>
        <Pagination.PrevButton>
          {#snippet child()}
            <Button variant="ghost" href="{$pageStore.route.id}?page={currentPage - 1}&size={size}">
              <ChevronLeftIcon />
              {m.general_previous()}
            </Button>
          {/snippet}
        </Pagination.PrevButton>
      </Pagination.Item>
      {#each pages as p (p.key)}
        {#if p.type === 'ellipsis'}
          <Pagination.Item>
            <Pagination.Ellipsis />
          </Pagination.Item>
        {:else}
          <Pagination.Item>
            <Pagination.Link page={p} isActive={currentPage === p.value}>
              {#snippet children()}
                <Button variant="ghost" href="{$pageStore.route.id}?page={p.value}&size={size}">
                  {p.value}
                </Button>
              {/snippet}
            </Pagination.Link>
          </Pagination.Item>
        {/if}
      {/each}
      <Pagination.Item>
        <Pagination.NextButton>
          {#snippet child()}
            <Button variant="ghost" href="{$pageStore.route.id}?page={currentPage + 1}&size={size}">
              {m.general_next()}
              <ChevronRightIcon />
            </Button>
          {/snippet}
        </Pagination.NextButton>
      </Pagination.Item>
    </Pagination.Content>
  {/snippet}
</Pagination.Root>

With this code, next/previous buttons works as expected, minus disabled function on them when you are at the end of the list. But Pagination.Link is acting strange. You need to click on a button twice to actually change the url, but only if the current page and button you want to press is between Pagination.Ellipsis.

Mind that child snippet can't be added to Pagination.Link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: feature Introduction of new functionality to the application
Projects
None yet
Development

No branches or pull requests

4 participants