diff --git a/packages/govuk-frontend-review/src/views/examples/pagination/index.njk b/packages/govuk-frontend-review/src/views/examples/pagination/index.njk new file mode 100644 index 0000000000..269a0b6934 --- /dev/null +++ b/packages/govuk-frontend-review/src/views/examples/pagination/index.njk @@ -0,0 +1,92 @@ +{% from "back-link/macro.njk" import govukBackLink %} +{% from "pagination/macro.njk" import govukPagination %} + +{% extends "layout.njk" %} + +{% block beforeContent %} + {{ govukBackLink({ + href: "/" + }) }} +{% endblock %} + +{% set veryShortPaginationItems = [ + { href: '#' }, + { href: '#' }, + { href: '#' } +] %} + +{% set shortPaginationItems = [ + { href: '#' }, + { href: '#' }, + { href: '#' }, + { href: '#' } +] %} + +{% set mediumPaginationItems = [ + { href: '#' }, + { href: '#' }, + { href: '#' }, + { href: '#' }, + { href: '#' }, + { href: '#' }, + { href: '#' } +] %} + +{% set longPaginationItems = [ + { href: '#' }, + { href: '#' }, + { href: '#' }, + { href: '#' }, + { href: '#' }, + { href: '#' }, + { href: '#' }, + { href: '#' }, + { href: '#' }, + { href: '#' }, + { href: '#' }, + { href: '#' } +] %} + +{% block content %} + +

Very short

+

Very short paginations (3 or fewer items) are small enough to not need to hide anything on any breakpoint.

+ +{%- for i in range(1, (veryShortPaginationItems | length) + 1) %} + {{ govukPagination({ + items: veryShortPaginationItems, + currentPage: i + }) }} +{%- endfor %} + +

Short

+

Short paginations (4 items, with default settings) can show all items on wide breakpoints, but hide some for narrow breakpoints.

+ +{%- for i in range(1, (shortPaginationItems | length) + 1) %} + {{ govukPagination({ + items: shortPaginationItems, + currentPage: i + }) }} +{%- endfor %} + +

Medium

+

Medium length paginations (5 to 7 items, with default settings) have the ability to sometimes be within 'neighbourly' range of both the start and end at the same time, showing all items at once on wide breakpoints, but also have enough items to require removing some in certain contexts and on narrow breakpoints.

+ +{%- for i in range(1, (mediumPaginationItems | length) + 1) %} + {{ govukPagination({ + items: mediumPaginationItems, + currentPage: i + }) }} +{%- endfor %} + +

Long

+

Long paginations (8 or more items with default settings) have enough items that they can never show all items at once. Some amount of truncation is always required, even on wider breakpoints.

+ +{%- for i in range(1, (longPaginationItems | length) + 1) %} + {{ govukPagination({ + items: longPaginationItems, + currentPage: i + }) }} +{%- endfor %} + +{% endblock %} diff --git a/packages/govuk-frontend/src/govuk/components/pagination/_index.scss b/packages/govuk-frontend/src/govuk/components/pagination/_index.scss index 439e46cf3d..99a7590019 100644 --- a/packages/govuk-frontend/src/govuk/components/pagination/_index.scss +++ b/packages/govuk-frontend/src/govuk/components/pagination/_index.scss @@ -37,8 +37,9 @@ } .govuk-pagination__item { - // Hide items on small screens except the prev/next items, - // non-link items and the first and last items + // Hide everything initially, we then unhide the stuff we actually want + // visible below. It's ridiculous but it works and avoids overly-specific + // selectors that mess with the cascade. display: none; // Center align pagination links in their parent list item so that they @@ -50,6 +51,19 @@ } } + .govuk-pagination__item:first-child, + .govuk-pagination__item:last-child, + .govuk-pagination__item--current, + .govuk-pagination__item--ellipses { + display: block; + } + + // If there are exactly three items, do not hide the middle item. + // Avoids an awkward and pointless '1 | ... | 3' situation. + .govuk-pagination__item:nth-child(2):nth-last-child(2) { + display: block; + } + .govuk-pagination__prev, .govuk-pagination__next { @include govuk-typography-weight-bold; @@ -70,12 +84,11 @@ padding-right: 0; } - // Only show first, last and non-link items on mobile - .govuk-pagination__item--current, - .govuk-pagination__item--ellipses, - .govuk-pagination__item:first-child, - .govuk-pagination__item:last-child { - display: block; + // Show 'collapsed only' items only on mobile + .govuk-pagination__item--collapsed-only { + @include govuk-media-query($from: tablet) { + display: none; + } } .govuk-pagination__item--current { diff --git a/packages/govuk-frontend/src/govuk/components/pagination/pagination.yaml b/packages/govuk-frontend/src/govuk/components/pagination/pagination.yaml index b8b93d691a..4d300217ae 100644 --- a/packages/govuk-frontend/src/govuk/components/pagination/pagination.yaml +++ b/packages/govuk-frontend/src/govuk/components/pagination/pagination.yaml @@ -16,14 +16,6 @@ params: type: string required: true description: The link's URL. - - name: current - type: boolean - required: false - description: Set to `true` to indicate the current page the user is on. - - name: ellipsis - type: boolean - required: false - description: Use this option if you want to specify an ellipsis at a given point between numbers. If you set this option as `true`, any other options for the item are ignored. - name: attributes type: object required: false @@ -70,6 +62,14 @@ params: type: object required: false description: The HTML attributes (for example, data attributes) you want to add to the anchor. + - name: currentPage + type: integer + required: true + description: The index of the current page within the set of `items`. This is a 1-based index, so that it matches the visible number that the component uses by default. + - name: neighbouringPages + type: integer + required: false + description: How many pages neighbouring the current page should be shown to the user. For example, when set to 2, links for up to 2 pages before and 2 pages after the current page will be visible, for a total of 5 pages. Defaults to 2. - name: landmarkLabel type: string required: false @@ -90,14 +90,11 @@ examples: href: '/previous' next: href: '/next' + currentPage: 2 items: - - number: 1 - href: '/page/1' - - number: 2 - href: '/page/2' - current: true - - number: 3 - href: '/page/3' + - href: '/page/1' + - href: '/page/2' + - href: '/page/3' - name: with custom navigation landmark data: previous: @@ -105,14 +102,11 @@ examples: next: href: '/next' landmarkLabel: 'search' + currentPage: 2 items: - - number: 1 - href: '/page/1' - - number: 2 - href: '/page/2' - current: true - - number: 3 - href: '/page/3' + - href: '/page/1' + - href: '/page/2' + - href: '/page/3' - name: with custom link and item text data: previous: @@ -121,12 +115,12 @@ examples: next: href: '/next' text: 'Next page' + currentPage: 2 items: - number: 'one' href: '/page/1' - number: 'two' href: '/page/2' - current: true - number: 'three' href: '/page/3' - name: with custom accessible labels on item links @@ -135,16 +129,13 @@ examples: href: '/previous' next: href: '/next' + currentPage: 2 items: - - number: 1 - href: '/page/1' + - href: '/page/1' visuallyHiddenText: '1st page' - - number: 2 - href: '/page/2' - current: true + - href: '/page/2' visuallyHiddenText: '2nd page (you are currently on this page)' - - number: 3 - href: '/page/3' + - href: '/page/3' visuallyHiddenText: '3rd page' - name: with many pages data: @@ -152,48 +143,139 @@ examples: href: '/previous' next: href: '/next' + currentPage: 10 items: - - number: 1 - href: '/page/1' - - ellipsis: true - - number: 8 - href: '/page/8' - - number: 9 - href: '/page/9' - - number: 10 - href: '/page/10' - current: true - - number: 11 - href: '/page/11' - - number: 12 - href: '/page/12' - - ellipsis: true - - number: 40 - href: '/page/40' + - href: '/page/1' + - href: '/page/2' + - href: '/page/3' + - href: '/page/4' + - href: '/page/5' + - href: '/page/6' + - href: '/page/7' + - href: '/page/8' + - href: '/page/9' + - href: '/page/10' + - href: '/page/11' + - href: '/page/12' + - href: '/page/13' + - href: '/page/14' + - href: '/page/15' + - href: '/page/16' + - href: '/page/17' + - href: '/page/18' + - href: '/page/19' + - href: '/page/20' - name: first page data: next: href: '/next' + currentPage: 1 items: - - number: 1 - href: '/page/1' - current: true - - number: 2 - href: '/page/2' - - number: 3 - href: '/page/3' + - href: '/page/1' + - href: '/page/2' + - href: '/page/3' - name: last page data: previous: href: '/previous' + currentPage: 3 items: - - number: 1 - href: '/page/1' - - number: 2 - href: '/page/2' - - number: 3 - href: '/page/3' - current: true + - href: '/page/1' + - href: '/page/2' + - href: '/page/3' + - name: bordering first page + data: + previous: + href: '/previous' + next: + href: '/next' + currentPage: 4 + items: + - href: '/page/1' + - href: '/page/2' + - href: '/page/3' + - href: '/page/4' + - href: '/page/5' + - href: '/page/6' + - href: '/page/7' + - href: '/page/8' + - href: '/page/9' + - href: '/page/10' + - name: bordering last page + data: + previous: + href: '/previous' + next: + href: '/next' + currentPage: 7 + items: + - href: '/page/1' + - href: '/page/2' + - href: '/page/3' + - href: '/page/4' + - href: '/page/5' + - href: '/page/6' + - href: '/page/7' + - href: '/page/8' + - href: '/page/9' + - href: '/page/10' + - name: with fewer neighbours + data: + previous: + href: '/previous' + next: + href: '/next' + currentPage: 4 + neighbouringPages: 1 + items: + - href: '/page/1' + - href: '/page/2' + - href: '/page/3' + - href: '/page/4' + - href: '/page/5' + - href: '/page/6' + - href: '/page/7' + - href: '/page/8' + - href: '/page/9' + - href: '/page/10' + - name: with more neighbours + data: + previous: + href: '/previous' + next: + href: '/next' + currentPage: 7 + neighbouringPages: 4 + items: + - href: '/page/1' + - href: '/page/2' + - href: '/page/3' + - href: '/page/4' + - href: '/page/5' + - href: '/page/6' + - href: '/page/7' + - href: '/page/8' + - href: '/page/9' + - href: '/page/10' + - name: with no neighbours + data: + previous: + href: '/previous' + next: + href: '/next' + currentPage: 7 + neighbouringPages: 0 + items: + - href: '/page/1' + - href: '/page/2' + - href: '/page/3' + - href: '/page/4' + - href: '/page/5' + - href: '/page/6' + - href: '/page/7' + - href: '/page/8' + - href: '/page/9' + - href: '/page/10' - name: with prev and next only data: previous: diff --git a/packages/govuk-frontend/src/govuk/components/pagination/template.njk b/packages/govuk-frontend/src/govuk/components/pagination/template.njk index a1bcdb1c10..7e24f3345a 100644 --- a/packages/govuk-frontend/src/govuk/components/pagination/template.njk +++ b/packages/govuk-frontend/src/govuk/components/pagination/template.njk @@ -1,5 +1,21 @@ {% set blockLevel = not params.items and (params.next or params.previous) %} +{% set currentPage = params.currentPage | int %} +{% set neighbouringPages = params.neighbouringPages | int if params.neighbouringPages !== undefined else 2 %} + +{% set visiblePagesLower = (currentPage - neighbouringPages) | int %} +{% set visiblePagesUpper = (currentPage + neighbouringPages) | int %} + +{% macro _paginationItem(index, item) %} + {%- set isCurrent = index == currentPage %} + {%- set number = item.number | default(index) %} +
  • + + {{- number -}} + +
  • +{% endmacro %} +