selectable tile

The Selectable Tile provides choices and allows the user to select a single option.

In order for selectable tiles to work correctly, the input tag needs a unique id attribute and the label tag needs the same for attribute. To ensure that only one options is selectable, the mutually-exclusive options need the same name attribute.

component variations

Selectable Tile

<div class="a-selectable-tile a-selectable-tile--radio -large">
  <input
    type="radio"
    name="Selectable Tile"
    id="unique_selectable-tile"
    aria-label="Selectable Tile"
  />
  <label for="unique_selectable-tile" aria-label="Selectable Tile">
    <figure class="a-image">
      <div class="a-image__ratioWrapper">
        <img
          src="https://brandguide-cdn.azureedge.net/frontend-kit/example-image-1600w.jpg"
          srcset="
            https://brandguide-cdn.azureedge.net/frontend-kit/example-image-400w.jpg   400w,
            https://brandguide-cdn.azureedge.net/frontend-kit/example-image-800w.jpg   800w,
            https://brandguide-cdn.azureedge.net/frontend-kit/example-image-1600w.jpg 1600w
          "
          alt="Lorem ipsum dolor sit amet"
        />
      </div>
    </figure>
    <div class="a-text">
      <p class="-size-m highlight a-text__headline">Headline</p>
      <p class="-size-s a-text__subheadline">Subheadline</p>
    </div>
  </label>
</div>

Selectable Tile Checkbox

<div class="a-selectable-tile a-selectable-tile--checkbox -large">
  <input
    type="checkbox"
    name="Selectable Tile Checkbox"
    id="unique_selectable-tile-checkbox"
    aria-label="Selectable Tile Checkbox"
  />
  <label
    for="unique_selectable-tile-checkbox"
    aria-label="Selectable Tile Checkbox"
  >
    <div class="checkbox-container"></div>
    <figure class="a-image">
      <div class="a-image__ratioWrapper">
        <img
          src="https://brandguide-cdn.azureedge.net/frontend-kit/example-image-1600w.jpg"
          srcset="
            https://brandguide-cdn.azureedge.net/frontend-kit/example-image-400w.jpg   400w,
            https://brandguide-cdn.azureedge.net/frontend-kit/example-image-800w.jpg   800w,
            https://brandguide-cdn.azureedge.net/frontend-kit/example-image-1600w.jpg 1600w
          "
          alt="Lorem ipsum dolor sit amet"
        />
      </div>
    </figure>
    <div class="a-text">
      <p class="-size-m highlight a-text__headline">Headline</p>
      <p class="-size-s a-text__subheadline">Subheadline</p>
    </div>
  </label>
</div>

Selectable Tile small

<div class="a-selectable-tile a-selectable-tile--radio -small">
  <input
    type="radio"
    name="Selectable Tile small"
    id="unique_selectable-tile-small"
    aria-label="Selectable Tile small"
  />
  <label for="unique_selectable-tile-small" aria-label="Selectable Tile small">
    <div class="a-text">
      <p class="-size-m highlight a-text__headline">Headline</p>
    </div>
  </label>
</div>

Selectable Tile small checkbox

<div class="a-selectable-tile a-selectable-tile--checkbox -small">
  <input
    type="checkbox"
    name="Selectable Tile small checkbox"
    id="unique_selectable-tile-small-checkbox"
    aria-label="Selectable Tile small checkbox"
  />
  <label
    for="unique_selectable-tile-small-checkbox"
    aria-label="Selectable Tile small checkbox"
  >
    <div class="checkbox-container"></div>
    <div class="a-text">
      <p class="-size-m highlight a-text__headline">Headline</p>
    </div>
  </label>
</div>

additional content

styles SCSS

@mixin checkbox-icon-tile {
  color: var(--major-accent__enabled__front__default);
  position: absolute;
  content: '';
  left: .75rem;
}

/* stylelint-disable no-descending-specificity */
.a-selectable-tile {
  position: relative;

  input {
    width: 0;
    opacity: 0;
    height: 0;
    -moz-appearance: none;
    position: absolute;
  }

  &.-small {
    label {
      display: flex;
    }

    .a-text {
      flex: auto;
      padding: 0.75rem;

      &__headline {
        margin: 0;
      }
    }
  }

  /* stylelint-disable selector-max-compound-selectors */
  &--radio input:focus-visible + label {
    @include focus-outside;

    --focus-offset-inner: 1px;
    --focus-offset-outer: 4px;
  }

  &--checkbox input:focus-visible + label .checkbox-container {
    &::after {
      position: absolute;
      content: '';
      height: 1.5rem;
      width: 1.5rem;
      outline: 3px solid var(--background);
      outline-offset: 0px;
    }

    &::before {
      outline: 3px solid var(--plain__enabled__front__default);
      outline-offset: 3px;
    }
  }
  /* stylelint-enable selector-max-compound-selectors */

  &--checkbox {
    // visualy hide checkbox button
    input[type='checkbox'] {
      // Cursors Definitions
      &:hover + label,
      &:active + label {
        cursor: pointer;
      }

      // unselected state
      &:hover + label .checkbox-container::before {
        background-color: var(--small__enabled__fill__hovered);
      }

      &:active + label .checkbox-container::before {
        background-color: var(--small__enabled__fill__pressed);
      }

      &:disabled + label .checkbox-container::before {
        background-color: var(--small__disabled__fill__default);
        pointer-events: none;
      }

      &:checked + label .checkbox-container::after {

        @include uiIconForComponents();
        @include checkbox-icon-tile();

        content: var(--ui-ic-checkmark);
      }

      // selected state
      &:checked + label .checkbox-container::before {
        background-color: var(--major-accent__enabled__fill__default);
      }

      &:checked:hover + label .checkbox-container::before {
        background-color: var(--major-accent__enabled__fill__hovered);
      }

      &:checked:active + label .checkbox-container::before {
        background-color: var(--major-accent__enabled__fill__pressed);
      }

      &:checked:disabled {
        + label .checkbox-container::before {
          background-color: var(--major-accent__disabled__fill__default);
        }

        + label .checkbox-container::after {
          color: var(--major-accent__disabled__front__default);
        }
      }
    }

    .checkbox-container {
      padding: .75rem;
      display: flex;

      &::before {
        position: relative;
        top: 0;
        left: 0;
        background-color: var(--small__enabled__fill__default);
        content: '';
        display: inline-block;
        height: 1.5rem;
        width: 1.5rem;
      }
    }

    &.-small {
      .a-text {
        padding: 0.75rem 0.75rem 0.75rem 0;
      }
    }
  }

  label {
    display: block;
    border: .0625rem solid var(--small__enabled__fill__default);
    cursor: pointer;
    position: relative;

    &:hover {
      border: .0625rem solid var(--small__enabled__fill__hovered);
    }
  }

  input[type='radio']:checked,
  input[type='checkbox']:checked {
    + label::before {
      content: '';
      position: absolute;
      background: transparent;
      border: .125rem solid var(--major-accent__enabled__fill__default);
      top: -.125rem;
      left: -.125rem;
      right: -.125rem;
      bottom: -.125rem;
    }

    + label {
      border-color: var(--major-accent__enabled__fill__default);
    }
  }

  .a-text {
    padding: .5rem .75rem .75rem;

    &__headline {
      margin: 0;
    }
  }
}