Tab

Navigation aid that allows users to switch between different sections or views within the same page.

Class name Type
.prs-tabs Component Container
.prs-tab Component For <button>
.prs-tabs-center Modifier Justify center
.prs-tab_active State Currently active
  • Default

    This is an Alpine.js example. In the code block you can see the reactive data and the attributes that need to be toggled based on that data.

    <div x-data="{ active: 1 }" x-id="['tab']">
      <div
        x-ref="tablist"
        @keydown.right.prevent.stop="$focus.wrap().next()"
        @keydown.home.prevent.stop="$focus.first()"
        @keydown.page-up.prevent.stop="$focus.first()"
        @keydown.left.prevent.stop="$focus.wrap().prev()"
        @keydown.end.prevent.stop="$focus.last()"
        @keydown.page-down.prevent.stop="$focus.last()"
        role="tablist"
        class="prs-tabs prs-tabs-center"
      >
        <template x-for="(i, index) in 3" hidden>
          <button
            @mousedown.prevent
            @click="active = index"
            @focus="active = index"
            :id="$id('tab', index)"
            :tabindex="index === active ? 0 : -1"
            :aria-selected="index === active"
            :class="index === active && 'prs-tab_active'"
            class="prs-tab"
            role="tab"
          >
            <span x-text="'Tab '+ i"></span>
            <template x-if="index === 1" hidden>
              <span class="prs-badge">5</span>
            </template>
          </button>
        </template>
      </div>
    </div>
    

CSS

Full Library

Component Only

.prs-tabs {
  display: flex;
  align-items: flex-end;
  justify-content: flex-start;

  &.prs-tabs-center {
    justify-content: center;
  }
}

.prs-tab {
  padding: 0.75rem 1rem 0.5rem;
  border-bottom: 4px solid transparent;
  color: var(--prs-c-gray-600);
  font-size: 0.875rem;
  line-height: 1.375rem;
  text-transform: uppercase;
  display: flex;
  align-items: center;
  gap: 0.25rem;
  cursor: pointer;
  transition-property: var(--prs-transition-property);
  transition-timing-function: var(--prs-transition-timing);
  transition-duration: var(--prs-transition-duration);

  &:hover {
    border-color: var(--prs-c-red-300);
  }

  &:focus-visible {
    outline: 2px solid var(--prs-c-aqua);
  }

  &:disabled {
    color: var(--prs-c-gray-400);
    cursor: not-allowed;
  }

  &.prs-tab_active {
    border-color: var(--prs-c-red);
    color: var(--prs-c-gray-900);

    &:hover {
      border-color: var(--prs-c-red-600);
    }
  }

  .prs-badge {
    padding: 0 0.5rem;
    border-color: transparent;
    width: fit-content;
    height: 1.375rem;
    background-color: var(--prs-c-aqua);
    color: var(--prs-c-white);
    font-weight: 600;
    font-size: 0.75em;
    line-height: 1.125em;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 9999px;
  }
}

Figma

Coming soon...