page indicator

Page indicator can be used to indicate to users the current page. It comes with two types: Dot-typed indicators (default) and numbered indicators (-numbered).

For numbered indicators, a maximum of 7 items are shown. If there are more pages, it is shown with three dots. See examples below.

Component events:

  • prevClicked - triggered when prev arrow was clicked
  • nextClicked - triggered when next arrow was clicked
  • clicked - triggered when other page was selected
  • indexChanged - triggered when an index of the selected page was changed
Each variant has an aria-label which needs to be set by the user.

component variations

default

<div
  class="a-page-indicator"
  data-start-index="1"
  data-max-length="7"
  role="navigation"
  aria-label="page indicator default"
>
  <div class="a-page-indicator__container">
    <button
      type="button"
      class="a-page-indicator__indicator -selected"
      data-index="1"
      aria-label="slide 1"
    ></button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="2"
      aria-label="slide 2"
    ></button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="3"
      aria-label="slide 3"
    ></button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="4"
      aria-label="slide 4"
    ></button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="5"
      aria-label="slide 5"
    ></button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="6"
      aria-label="slide 6"
    ></button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="7"
      aria-label="slide 7"
    ></button>
  </div>
</div>

default disabled

<div
  class="a-page-indicator -disabled"
  data-start-index="1"
  data-max-length="7"
  role="navigation"
  aria-label="page indicator default disabled"
>
  <div class="a-page-indicator__container">
    <button
      type="button"
      class="a-page-indicator__indicator -selected"
      data-index="1"
      aria-label="slide 1"
      aria-disabled="true"
    ></button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="2"
      aria-label="slide 2"
      aria-disabled="true"
    ></button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="3"
      aria-label="slide 3"
      aria-disabled="true"
    ></button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="4"
      aria-label="slide 4"
      aria-disabled="true"
    ></button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="5"
      aria-label="slide 5"
      aria-disabled="true"
    ></button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="6"
      aria-label="slide 6"
      aria-disabled="true"
    ></button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="7"
      aria-label="slide 7"
      aria-disabled="true"
    ></button>
  </div>
</div>

numbered

<div
  class="a-page-indicator a-page-indicator--numbered"
  data-start-index="1"
  data-max-length="7"
  role="navigation"
  aria-label="page indicator numbered"
>
  <button
    type="button"
    class="a-page-indicator__caret -left"
    aria-label="go to previous page"
  ></button>
  <div class="a-page-indicator__container">
    <button
      type="button"
      class="a-page-indicator__indicator -selected"
      data-index="1"
      aria-label="slide 1"
    >
      <span>1</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="2"
      aria-label="slide 2"
    >
      <span>2</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="3"
      aria-label="slide 3"
    >
      <span>3</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="4"
      aria-label="slide 4"
    >
      <span>4</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="5"
      aria-label="slide 5"
    >
      <span>5</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="6"
      aria-label="slide 6"
    >
      <span>6</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="7"
      aria-label="slide 7"
    >
      <span>7</span>
    </button>
  </div>
  <button
    type="button"
    class="a-page-indicator__caret -right"
    aria-label="go to next page"
  ></button>
</div>

numbered 200 pages

<div
  class="a-page-indicator a-page-indicator--numbered"
  data-start-index="1"
  data-max-length="200"
  role="navigation"
  aria-label="page indicator numbered 200 pages"
>
  <button
    type="button"
    class="a-page-indicator__caret -left"
    aria-label="go to previous page"
  ></button>
  <div class="a-page-indicator__container">
    <button
      type="button"
      class="a-page-indicator__indicator -selected"
      data-index="1"
      aria-label="slide 1"
    >
      <span>1</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="2"
      aria-label="slide 2"
    >
      <span>2</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="3"
      aria-label="slide 3"
    >
      <span>3</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="4"
      aria-label="slide 4"
    >
      <span>4</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="5"
      aria-label="slide 5"
    >
      <span>5</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      aria-label="slide ..."
    >
      <span>...</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="200"
      aria-label="slide 200"
    >
      <span>200</span>
    </button>
  </div>
  <button
    type="button"
    class="a-page-indicator__caret -right"
    aria-label="go to next page"
  ></button>
</div>

numbered 20 pages selected 5

<div
  class="a-page-indicator a-page-indicator--numbered"
  data-start-index="5"
  data-max-length="20"
  role="navigation"
  aria-label="page indicator numbered 20 pages selected 5"
>
  <button
    type="button"
    class="a-page-indicator__caret -left"
    aria-label="go to previous page"
  ></button>
  <div class="a-page-indicator__container">
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="1"
      aria-label="slide 1"
    >
      <span>1</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      aria-label="slide ..."
    >
      <span>...</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="4"
      aria-label="slide 4"
    >
      <span>4</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator -selected"
      data-index="5"
      aria-label="slide 5"
    >
      <span>5</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="6"
      aria-label="slide 6"
    >
      <span>6</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      aria-label="slide ..."
    >
      <span>...</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="20"
      aria-label="slide 20"
    >
      <span>20</span>
    </button>
  </div>
  <button
    type="button"
    class="a-page-indicator__caret -right"
    aria-label="go to next page"
  ></button>
</div>

numbered 20 pages selected 18 disabled

<div
  class="a-page-indicator -disabled a-page-indicator--numbered"
  data-start-index="18"
  data-max-length="20"
  role="navigation"
  aria-label="page indicator numbered 20 pages selected 18 disabled"
>
  <button
    type="button"
    class="a-page-indicator__caret -left"
    aria-label="go to previous page"
    aria-disabled="true"
  ></button>
  <div class="a-page-indicator__container">
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="1"
      aria-label="slide 1"
      aria-disabled="true"
    >
      <span>1</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      aria-label="slide ..."
      aria-disabled="true"
    >
      <span>...</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="16"
      aria-label="slide 16"
      aria-disabled="true"
    >
      <span>16</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="17"
      aria-label="slide 17"
      aria-disabled="true"
    >
      <span>17</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator -selected"
      data-index="18"
      aria-label="slide 18"
      aria-disabled="true"
    >
      <span>18</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="19"
      aria-label="slide 19"
      aria-disabled="true"
    >
      <span>19</span>
    </button>
    <button
      type="button"
      class="a-page-indicator__indicator"
      data-index="20"
      aria-label="slide 20"
      aria-disabled="true"
    >
      <span>20</span>
    </button>
  </div>
  <button
    type="button"
    class="a-page-indicator__caret -right"
    aria-label="go to next page"
    aria-disabled="true"
  ></button>
</div>

additional content

styles SCSS

.a-page-indicator {
  display: flex;
  align-items: center;

  &__container {
    display: flex;
    flex-wrap: nowrap;
  }

  &.-disabled {
    pointer-events: none;
  }

  &__indicator {
    width: 0.5rem;
    height: 0.5rem;
    margin: 0.5rem;
    background-color: var(--small__enabled__fill__default);
    color: var(--small__enabled__front__default);
    border: none;
    padding: 0;
    border-radius: 0.25rem;
    cursor: pointer;

    &:hover {
      background-color: var(--small__enabled__fill__hovered);
      color: var(--small__enabled__front__hovered);
    }

    &:active {
      background-color: var(--small__enabled__fill__pressed);
      color: var(--small__enabled__front__pressed);
    }

    &:focus-visible {
      @include focus-outside;
      --focus-border-radius: 50%;
    }

    &.-selected {
      width: 0.75rem;
      height: 0.75rem;
      margin: 0.375rem;
      background-color: var(--major-accent__enabled__fill__default);
      color: var(--major-accent__enabled__front__default);
      border-radius: 0.375rem;

      &:hover {
        background-color: var(--major-accent__enabled__fill__hovered);
        color: var(--major-accent__enabled__front__hovered);
      }

      &:active {
        background-color: var(--major-accent__enabled__fill__pressed);
        color: var(--major-accent__enabled__front__pressed);
      }

      .-disabled & {
        background-color: var(--major-accent__disabled__fill__default);
        color: var(--major-accent__disabled__front__default);
      }
    }

    .-disabled & {
      background-color: var(--small__disabled__fill__default);
      color: var(--small__disabled__front__default);
    }
  }

  &__caret {
    height: 1.5rem;
    width: 1.5rem;
    background-color: var(--integrated__enabled__fill__default);
    border: none;
    padding: 0;

    &::after {
      @include uiIconForComponents();

      color: var(--integrated__enabled__front__default);
      position: relative;
      cursor: pointer;
      content: "";
    }

    &:first-child {
      margin-right: 0.5rem;
    }

    &:last-child {
      margin-left: 0.5rem;
    }

    &:hover::after {
      color: var(--integrated__enabled__front__hovered);
    }

    &:active::after {
      color: var(--integrated__enabled__front__pressed);
    }

    &:focus-visible {
      @include focus-outside;
    }

    &.-left::after {
      content: var(--ui-ic-left);
    }

    &.-right::after {
      content: var(--ui-ic-right);
    }

    &.-end {
      &::after {
        cursor: auto;
        color: var(--integrated__disabled__front__default);
      }
    }
  }
}

.a-page-indicator--numbered {
  .a-page-indicator__indicator {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 2rem;
    min-width: 2rem;
    width: auto;
    border-radius: 1rem;
    padding: 0 0.5rem;
    margin: 0 0.25rem;
    background-color: var(--plain__enabled__fill__default);
    color: var(--plain__enabled__front__default);

    &:not([data-index]) {
      pointer-events: none;
    }

    &:hover {
      background-color: var(--plain__enabled__fill__hovered);
      color: var(--plain__enabled__front__hovered);
    }

    &:active {
      background-color: var(--plain__enabled__fill__pressed);
      color: var(--plain__enabled__front__pressed);
    }

    &:focus-visible {
      --focus-border-radius: 1rem;
    }

    span {
      user-select: none;
    }

    &.-selected {
      background-color: var(--major-accent__enabled__fill__default);
      color: var(--major-accent__enabled__front__default);

      &:hover {
        background-color: var(--major-accent__enabled__fill__hovered);
        color: var(--major-accent__enabled__front__hovered);
      }

      &:active {
        background-color: var(--major-accent__enabled__fill__pressed);
        color: var(--major-accent__enabled__front__pressed);
      }
    }
  }

  &.-disabled .a-page-indicator {
    &__caret {
      background-color: var(--integrated__disabled__fill__default);

      &::after {
        cursor: auto;
        color: var(--integrated__disabled__front__default);
      }
    }

    &__indicator {
      background-color: var(--plain__disabled__fill__default);
      color: var(--plain__disabled__front__default);

      &.-selected {
        background-color: var(--major-accent__disabled__fill__default);
        color: var(--major-accent__disabled__front__default);
      }
    }
  }
}