# <aihio-pagination>

Navigation between the pages of a long list (a pager): previous and next, the first and last page, and the pages around the current one. With href each page is a link with its own address; without it each page is a button your code answers. Use it under a table, search results, or a grid of cards when the whole list is too long to show at once.

Intents: `navigation`.

## Attributes

- `page` (number): The current page, from 1. Default: `1`.
- `pages` (number): How many pages there are. With fewer than two there is nothing to page through, and nothing is shown.
- `href` (string): The address of a page, with {page} where its number goes: "/invoices?page={page}". With it each page is a link that can open in a new tab and needs no script of yours. Without it each page is a button, and picking one sets page.
- `previous-text` (string): The previous page control's text. For localisation. Default: `Previous`.
- `next-text` (string): The next page control's text. For localisation. Default: `Next`.
- `page-text` (string): Each page's accessible name, with {page} for its number, and what is announced when a button changes the page. For localisation (e.g. "Sivu {page}"). Default: `Page {page}`.

## Properties

- `page` (`number`): Get or set the current page. Setting it fires no aihio-page.
- `pages` (`number`): Get or set how many pages there are.

## Events

- `aihio-page` (detail: page: number): Fired when the person picks a page, before it opens: a link then navigates, and a button sets page. Call preventDefault() to open it yourself, as a client-side router does. A click that opens a link in a new tab or window is left to the browser.

## Accessibility obligations

- (error, pagination-pages) When pages is missing or not a whole number, or page is outside 1 to pages: Set pages to how many pages there are, and page to the current one, counting from 1.
- (error, pagination-href) When href is set without {page}: Put {page} where the page number goes in href. Without it every page links to the same address.
- (warn, pagination-label) When more than one aihio-pagination is on the page: Name each one after the list it pages through, aria-label="Invoice pages", so the landmarks can be told apart.

## Examples

### Pages with their own address

With href each page is a link: it can open in a new tab or be bookmarked, and needs no script of yours.

```html
<aihio-pagination page="4" pages="12" href="/invoices?page={page}" aria-label="Invoice pages"></aihio-pagination>
```

### Many pages

Past seven pages the list keeps the first and last and the pages beside the current one, and stays seven long.

```html
<aihio-pagination page="57" pages="4000" href="/requests?page={page}" aria-label="Request pages"></aihio-pagination>
```

### Pages your code swaps in

Without href each page is a button. Picking one sets page and fires aihio-page with the page to show; call preventDefault() to set page yourself, from state.

```html
<aihio-pagination page="1" pages="5" aria-label="Result pages"></aihio-pagination>
```

### Under a table

The table shows one page of the records, sorted by your code or the server with manual-sort, and says which ones it shows.

```html
<aihio-stack gap="md">
  <aihio-table manual-sort>
    <table aria-label="Invoices">
      <thead>
        <tr>
          <th scope="col" data-sortable="invoice" aria-sort="ascending">Invoice</th>
          <th scope="col" data-sortable="amount" data-numeric>Amount</th>
        </tr>
      </thead>
      <tbody>
        <tr><th scope="row"><a href="/invoices/1051">INV-1051</a></th><td data-numeric>€480.00</td></tr>
        <tr><th scope="row"><a href="/invoices/1052">INV-1052</a></th><td data-numeric>€2,150.00</td></tr>
        <tr><th scope="row"><a href="/invoices/1053">INV-1053</a></th><td data-numeric>€95.20</td></tr>
      </tbody>
    </table>
  </aihio-table>
  <aihio-cluster justify="between">
    <p>Showing 51–53 of 53 invoices</p>
    <aihio-pagination page="3" pages="3" href="/invoices?page={page}" aria-label="Invoice pages"></aihio-pagination>
  </aihio-cluster>
</aihio-stack>
```

### In another language

previous-text, next-text, and page-text put the controls in the page's language; name the landmark in it too.

```html
<aihio-pagination page="2" pages="6" href="/laskut?sivu={page}" aria-label="Laskujen sivut" previous-text="Edellinen" next-text="Seuraava" page-text="Sivu {page}"></aihio-pagination>
```

## Mistakes

### The current page is page and the number of pages is pages. Nothing reads current or total, so this shows nothing.

Don't (aihio lint: unknown-attribute):

```html
<aihio-pagination current="3" total="12" href="/invoices?page={page}"></aihio-pagination>
```

Do:

```html
<aihio-pagination page="3" pages="12" href="/invoices?page={page}"></aihio-pagination>
```

### Without {page} in href every page links to the same address.

Don't (aihio lint: pagination-href):

```html
<aihio-pagination page="3" pages="12" href="/invoices?page="></aihio-pagination>
```

Do:

```html
<aihio-pagination page="3" pages="12" href="/invoices?page={page}"></aihio-pagination>
```

### Pages count from 1. Page 0 is not a page, so no page is marked current.

Don't (aihio lint: pagination-pages):

```html
<aihio-pagination page="0" pages="12" href="/invoices?page={page}"></aihio-pagination>
```

Do:

```html
<aihio-pagination page="1" pages="12" href="/invoices?page={page}"></aihio-pagination>
```

### Two landmarks both named "Pagination" cannot be told apart in a screen reader's list of landmarks. Name each after the list it pages through.

Don't (aihio lint: pagination-label):

```html
<aihio-pagination page="1" pages="4" href="/invoices?page={page}"></aihio-pagination>
<aihio-pagination page="2" pages="9" href="/payments?page={page}"></aihio-pagination>
```

Do:

```html
<aihio-pagination page="1" pages="4" href="/invoices?page={page}" aria-label="Invoice pages"></aihio-pagination>
<aihio-pagination page="2" pages="9" href="/payments?page={page}" aria-label="Payment pages"></aihio-pagination>
```
