Menu

Switch icon

The Switch Icon component is used to create a transition between two icons. You can use any icon, both line and filled version.

Default markup

The icon transition is triggered by adding an .active class to the switch-icon component.

<button type="button" class="switch-icon" data-bs-toggle="switch-icon" aria-pressed="false" aria-label="Like">
  <span class="switch-icon-a text-secondary">
    <!-- Download SVG icon from http://tabler.io/icons/icon/heart -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
      <path d="M19.5 12.572l-7.5 7.428l-7.5 -7.428a5 5 0 1 1 7.5 -6.566a5 5 0 1 1 7.5 6.572" />
    </svg>
  </span>
  <span class="switch-icon-b text-red">
    <!-- Download SVG icon from http://tabler.io/icons/icon/heart -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" class="icon">
      <path d="M6.979 3.074a6 6 0 0 1 4.988 1.425l.037 .033l.034 -.03a6 6 0 0 1 4.733 -1.44l.246 .036a6 6 0 0 1 3.364 10.008l-.18 .185l-.048 .041l-7.45 7.379a1 1 0 0 1 -1.313 .082l-.094 -.082l-7.493 -7.422a6 6 0 0 1 3.176 -10.215z" />
    </svg>
  </span>
</button>

Switch animations

You can also add a fancy animation to add variety to your button. See demo below:

<button type="button" class="switch-icon" data-bs-toggle="switch-icon" aria-pressed="false" aria-label="Select">
  <span class="switch-icon-a text-secondary">
    <!-- Download SVG icon from http://tabler.io/icons/icon/circle -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
      <path d="M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0" />
    </svg>
  </span>
  <span class="switch-icon-b text-primary">
    <!-- Download SVG icon from http://tabler.io/icons/icon/circle -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" class="icon">
      <path d="M7 3.34a10 10 0 1 1 -4.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 4.995 -8.336z" />
    </svg>
  </span>
</button>
<button type="button" class="switch-icon switch-icon-fade" data-bs-toggle="switch-icon" aria-pressed="false" aria-label="Like">
  <span class="switch-icon-a text-secondary">
    <!-- Download SVG icon from http://tabler.io/icons/icon/heart -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
      <path d="M19.5 12.572l-7.5 7.428l-7.5 -7.428a5 5 0 1 1 7.5 -6.566a5 5 0 1 1 7.5 6.572" />
    </svg>
  </span>
  <span class="switch-icon-b text-red">
    <!-- Download SVG icon from http://tabler.io/icons/icon/heart -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" class="icon">
      <path d="M6.979 3.074a6 6 0 0 1 4.988 1.425l.037 .033l.034 -.03a6 6 0 0 1 4.733 -1.44l.246 .036a6 6 0 0 1 3.364 10.008l-.18 .185l-.048 .041l-7.45 7.379a1 1 0 0 1 -1.313 .082l-.094 -.082l-7.493 -7.422a6 6 0 0 1 3.176 -10.215z" />
    </svg>
  </span>
</button>
<button type="button" class="switch-icon switch-icon-scale" data-bs-toggle="switch-icon" aria-pressed="false" aria-label="Add to favorites">
  <span class="switch-icon-a text-secondary">
    <!-- Download SVG icon from http://tabler.io/icons/icon/star -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
      <path d="M12 17.75l-6.172 3.245l1.179 -6.873l-5 -4.867l6.9 -1l3.086 -6.253l3.086 6.253l6.9 1l-5 4.867l1.179 6.873l-6.158 -3.245" />
    </svg>
  </span>
  <span class="switch-icon-b text-yellow">
    <!-- Download SVG icon from http://tabler.io/icons/icon/star -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" class="icon">
      <path d="M8.243 7.34l-6.38 .925l-.113 .023a1 1 0 0 0 -.44 1.684l4.622 4.499l-1.09 6.355l-.013 .11a1 1 0 0 0 1.464 .944l5.706 -3l5.693 3l.1 .046a1 1 0 0 0 1.352 -1.1l-1.091 -6.355l4.624 -4.5l.078 -.085a1 1 0 0 0 -.633 -1.62l-6.38 -.926l-2.852 -5.78a1 1 0 0 0 -1.794 0l-2.853 5.78z" />
    </svg>
  </span>
</button>
<button type="button" class="switch-icon switch-icon-flip" data-bs-toggle="switch-icon" aria-pressed="false" aria-label="Vote up">
  <span class="switch-icon-a text-secondary">
    <!-- Download SVG icon from http://tabler.io/icons/icon/thumb-up -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
      <path d="M7 11v8a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1v-7a1 1 0 0 1 1 -1h3a4 4 0 0 0 4 -4v-1a2 2 0 0 1 4 0v5h3a2 2 0 0 1 2 2l-1 5a2 3 0 0 1 -2 2h-7a3 3 0 0 1 -3 -3" />
    </svg>
  </span>
  <span class="switch-icon-b text-blue">
    <!-- Download SVG icon from http://tabler.io/icons/icon/thumb-up -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" class="icon">
      <path d="M13 3a3 3 0 0 1 2.995 2.824l.005 .176v4h2a3 3 0 0 1 2.98 2.65l.015 .174l.005 .176l-.02 .196l-1.006 5.032c-.381 1.626 -1.502 2.796 -2.81 2.78l-.164 -.008h-8a1 1 0 0 1 -.993 -.883l-.007 -.117l.001 -9.536a1 1 0 0 1 .5 -.865a2.998 2.998 0 0 0 1.492 -2.397l.007 -.202v-1a3 3 0 0 1 3 -3z" />
      <path d="M5 10a1 1 0 0 1 .993 .883l.007 .117v9a1 1 0 0 1 -.883 .993l-.117 .007h-1a2 2 0 0 1 -1.995 -1.85l-.005 -.15v-7a2 2 0 0 1 1.85 -1.995l.15 -.005h1z" />
    </svg>
  </span>
</button>
<button type="button" class="switch-icon switch-icon-slide-up" data-bs-toggle="switch-icon" aria-pressed="false" aria-label="Toggle">
  <span class="switch-icon-a text-secondary">
    <svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
      <path stroke="none" d="M0 0h24v24H0z" fill="none" />
      <path d="M22 4.01c-1 .49 -1.98 .689 -3 .99c-1.121 -1.265 -2.783 -1.335 -4.38 -.737s-2.643 2.06 -2.62 3.737v1c-3.245 .083 -6.135 -1.395 -8 -4c0 0 -4.182 7.433 4 11c-1.872 1.247 -3.739 2.088 -6 2c3.308 1.803 6.913 2.423 10.034 1.517c3.58 -1.04 6.522 -3.723 7.651 -7.742a13.84 13.84 0 0 0 .497 -3.753c-.002 -.249 1.51 -2.772 1.818 -4.013z" />
    </svg>
  </span>
  <span class="switch-icon-b text-azure">
    <svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
      <path stroke="none" d="M0 0h24v24H0z" fill="none" />
      <path d="M22 4.01c-1 .49 -1.98 .689 -3 .99c-1.121 -1.265 -2.783 -1.335 -4.38 -.737s-2.643 2.06 -2.62 3.737v1c-3.245 .083 -6.135 -1.395 -8 -4c0 0 -4.182 7.433 4 11c-1.872 1.247 -3.739 2.088 -6 2c3.308 1.803 6.913 2.423 10.034 1.517c3.58 -1.04 6.522 -3.723 7.651 -7.742a13.84 13.84 0 0 0 .497 -3.753c-.002 -.249 1.51 -2.772 1.818 -4.013z" />
    </svg>
  </span>
</button>
<button type="button" class="switch-icon switch-icon-slide-left" data-bs-toggle="switch-icon" aria-pressed="false" aria-label="Toggle">
  <span class="switch-icon-a text-secondary">
    <!-- Download SVG icon from http://tabler.io/icons/icon/check -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
      <path d="M5 12l5 5l10 -10" />
    </svg>
  </span>
  <span class="switch-icon-b text-red">
    <!-- Download SVG icon from http://tabler.io/icons/icon/x -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
      <path d="M18 6l-12 12" />
      <path d="M6 6l12 12" />
    </svg>
  </span>
</button>
<button type="button" class="switch-icon switch-icon-slide-down" data-bs-toggle="switch-icon" aria-pressed="false" aria-label="Toggle">
  <span class="switch-icon-a text-secondary">
    <!-- Download SVG icon from http://tabler.io/icons/icon/arrow-down -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
      <path d="M12 5l0 14" />
      <path d="M18 13l-6 6" />
      <path d="M6 13l6 6" />
    </svg>
  </span>
  <span class="switch-icon-b text-secondary">
    <!-- Download SVG icon from http://tabler.io/icons/icon/arrow-up -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
      <path d="M12 5l0 14" />
      <path d="M18 11l-6 -6" />
      <path d="M6 11l6 -6" />
    </svg>
  </span>
</button>
<button type="button" class="switch-icon switch-icon-slide-end" data-bs-toggle="switch-icon" aria-pressed="false" aria-label="Toggle">
  <span class="switch-icon-a text-secondary">
    <!-- Download SVG icon from http://tabler.io/icons/icon/car -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
      <path d="M5 17a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
      <path d="M15 17a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
      <path d="M5 17h-2v-6l2 -5h9l4 5h1a2 2 0 0 1 2 2v4h-2m-4 0h-6m-6 -6h15m-6 0v-5" />
    </svg>
  </span>
  <span class="switch-icon-b text-secondary">
    <!-- Download SVG icon from http://tabler.io/icons/icon/scooter -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
      <path d="M16 17a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
      <path d="M4 17a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
      <path d="M8 17h5a6 6 0 0 1 5 -5v-5a2 2 0 0 0 -2 -2h-1" />
    </svg>
  </span>
</button>

In an action button

A switch icon can sit inside a button, for example a btn-action in a table row or a card header. Put data-bs-toggle="switch-icon" and aria-pressed on the button and the switch-icon inside it: Tabler toggles the icon and keeps the state on the button, which also provides the hover, focus and target size.

<div class="btn-actions">
  <button type="button" class="btn btn-action" data-bs-toggle="switch-icon" aria-pressed="false" aria-label="Like">
    <span class="switch-icon switch-icon-scale">
      <span class="switch-icon-a">
        <!-- Download SVG icon from http://tabler.io/icons/icon/heart -->
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
          <path d="M19.5 12.572l-7.5 7.428l-7.5 -7.428a5 5 0 1 1 7.5 -6.566a5 5 0 1 1 7.5 6.572" />
        </svg>
      </span>
      <span class="switch-icon-b text-red">
        <!-- Download SVG icon from http://tabler.io/icons/icon/heart -->
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" class="icon">
          <path d="M6.979 3.074a6 6 0 0 1 4.988 1.425l.037 .033l.034 -.03a6 6 0 0 1 4.733 -1.44l.246 .036a6 6 0 0 1 3.364 10.008l-.18 .185l-.048 .041l-7.45 7.379a1 1 0 0 1 -1.313 .082l-.094 -.082l-7.493 -7.422a6 6 0 0 1 3.176 -10.215z" />
        </svg>
      </span>
    </span>
  </button>
  <button type="button" class="btn btn-action" data-bs-toggle="switch-icon" aria-pressed="false" aria-label="Add to favorites">
    <span class="switch-icon switch-icon-scale">
      <span class="switch-icon-a">
        <!-- Download SVG icon from http://tabler.io/icons/icon/star -->
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
          <path d="M12 17.75l-6.172 3.245l1.179 -6.873l-5 -4.867l6.9 -1l3.086 -6.253l3.086 6.253l6.9 1l-5 4.867l1.179 6.873l-6.158 -3.245" />
        </svg>
      </span>
      <span class="switch-icon-b text-yellow">
        <!-- Download SVG icon from http://tabler.io/icons/icon/star -->
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" class="icon">
          <path d="M8.243 7.34l-6.38 .925l-.113 .023a1 1 0 0 0 -.44 1.684l4.622 4.499l-1.09 6.355l-.013 .11a1 1 0 0 0 1.464 .944l5.706 -3l5.693 3l.1 .046a1 1 0 0 0 1.352 -1.1l-1.091 -6.355l4.624 -4.5l.078 -.085a1 1 0 0 0 -.633 -1.62l-6.38 -.926l-2.852 -5.78a1 1 0 0 0 -1.794 0l-2.853 5.78z" />
        </svg>
      </span>
    </span>
  </button>
  <button type="button" class="btn btn-action" data-bs-toggle="switch-icon" aria-pressed="false" aria-label="Bookmark">
    <span class="switch-icon switch-icon-flip">
      <span class="switch-icon-a">
        <!-- Download SVG icon from http://tabler.io/icons/icon/bookmark -->
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
          <path d="M18 7v14l-6 -4l-6 4v-14a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4" />
        </svg>
      </span>
      <span class="switch-icon-b text-primary">
        <!-- Download SVG icon from http://tabler.io/icons/icon/bookmark -->
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" class="icon">
          <path d="M14 2a5 5 0 0 1 5 5v14a1 1 0 0 1 -1.555 .832l-5.445 -3.63l-5.444 3.63a1 1 0 0 1 -1.55 -.72l-.006 -.112v-14a5 5 0 0 1 5 -5h4z" />
        </svg>
      </span>
    </span>
  </button>
</div>

Loading state

Add switch-icon-loading to show a spinner in place of the icons, for example while a request is in flight. The button ignores clicks in this state. Set aria-busy="true" with it, so assistive technology knows the control is busy.

<button type="button" class="switch-icon switch-icon-loading" data-bs-toggle="switch-icon" aria-pressed="false" aria-busy="true" aria-label="Add to favorites">
  <span class="switch-icon-a text-secondary">
    <!-- Download SVG icon from http://tabler.io/icons/icon/star -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
      <path d="M12 17.75l-6.172 3.245l1.179 -6.873l-5 -4.867l6.9 -1l3.086 -6.253l3.086 6.253l6.9 1l-5 4.867l1.179 6.873l-6.158 -3.245" />
    </svg>
  </span>
  <span class="switch-icon-b text-yellow">
    <!-- Download SVG icon from http://tabler.io/icons/icon/star -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" class="icon">
      <path d="M8.243 7.34l-6.38 .925l-.113 .023a1 1 0 0 0 -.44 1.684l4.622 4.499l-1.09 6.355l-.013 .11a1 1 0 0 0 1.464 .944l5.706 -3l5.693 3l.1 .046a1 1 0 0 0 1.352 -1.1l-1.091 -6.355l4.624 -4.5l.078 -.085a1 1 0 0 0 -.633 -1.62l-6.38 -.926l-2.852 -5.78a1 1 0 0 0 -1.794 0l-2.853 5.78z" />
    </svg>
  </span>
</button>
<button type="button" class="switch-icon switch-icon-loading" data-bs-toggle="switch-icon" aria-pressed="false" aria-busy="true" aria-label="Like">
  <span class="switch-icon-a text-secondary">
    <!-- Download SVG icon from http://tabler.io/icons/icon/heart -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
      <path d="M19.5 12.572l-7.5 7.428l-7.5 -7.428a5 5 0 1 1 7.5 -6.566a5 5 0 1 1 7.5 6.572" />
    </svg>
  </span>
  <span class="switch-icon-b text-red">
    <!-- Download SVG icon from http://tabler.io/icons/icon/heart -->
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" class="icon">
      <path d="M6.979 3.074a6 6 0 0 1 4.988 1.425l.037 .033l.034 -.03a6 6 0 0 1 4.733 -1.44l.246 .036a6 6 0 0 1 3.364 10.008l-.18 .185l-.048 .041l-7.45 7.379a1 1 0 0 1 -1.313 .082l-.094 -.082l-7.493 -7.422a6 6 0 0 1 3.176 -10.215z" />
    </svg>
  </span>
</button>

Wait for a request

Every toggle fires toggle.bs.switch-icon on the button before the state changes. event.active is the state the button is about to switch to. Pass a promise to event.wait() and the button shows the loading state until it settles: it switches when the promise resolves and stays as it was when it rejects. Call event.preventDefault() to cancel the toggle.

<button type="button" class="switch-icon" data-bs-toggle="switch-icon" data-id="42" aria-pressed="false" aria-label="Star">
  <span class="switch-icon-a text-secondary">…</span>
  <span class="switch-icon-b text-yellow">…</span>
</button>
document.querySelectorAll('[data-bs-toggle="switch-icon"]').forEach((button) => {
  button.addEventListener('toggle.bs.switch-icon', (event) => {
    event.wait(fetch(`/api/items/${button.dataset.id}/star`, { method: event.active ? 'PUT' : 'DELETE' }));
  });
});

The event bubbles, so one listener on a list can serve all of its buttons.

JavaScript

Tabler wraps the button in a SwitchIcon component that works like the Bootstrap components: it is created once per element and stored on it. On page load Tabler creates one for every element with data-bs-toggle="switch-icon", and a click toggles the active class and aria-pressed. This is the code that runs:

initAll(SELECTOR_DATA_TOGGLE, SwitchIcon)

Create the component yourself for a button added later, or change the state from code:

const favorite = tabler.SwitchIcon.getOrCreateInstance(document.getElementById('favorite'));
favorite.toggle(); // flip
favorite.toggle(true); // force on

Every toggle fires toggle.bs.switch-icon before the change (cancelable, see Wait for a request) and change.bs.switch-icon after it, both with the new state in event.active:

document.getElementById('favorite').addEventListener('change.bs.switch-icon', (event) => {
  console.log(event.active ? 'added to favorites' : 'removed from favorites');
});
Method Description
toggle(force) Flips the state, or sets it when force is true or false. Fires toggle.bs.switch-icon, then updates aria-pressed and fires change.bs.switch-icon. Does nothing while loading.
isActive Getter. true when the switch icon has the active class.
isLoading Getter. true while a promise passed to event.wait() is pending.
dispose() Removes the click handler and the component from the element.
getInstance(element) Static. Returns the component for the element, or null.
getOrCreateInstance(element) Static. Returns the component for the element and creates it when needed.

Accessibility

  • A switch icon is a toggle button. Give it type="button", an aria-label saying what it toggles, and aria-pressed for the state. Tabler keeps aria-pressed in sync, and fills it in from the active class when the markup leaves it out.
  • The two icons are decoration. The state lives in aria-pressed, not in which icon is visible.
  • Colour alone should not carry the state. A filled red heart and an outlined gray one differ in shape too, which is what makes them readable.
  • The button box is at least 24×24px ($switch-icon-min-size) with the icon centered inside, to meet the WCAG target size. Set --tblr-switch-icon-min-size to change it.
  • To disable a switch icon use the disabled attribute, or aria-disabled="true" when it has to stay focusable. Tabler ignores clicks on both, and on the disabled class, which alone would still let Enter and Space toggle it.
  • While a request is pending, the button carries aria-busy="true" and ignores clicks, so a double click cannot send the request twice.
  • The spinner slows down under prefers-reduced-motion, and the icon transitions are switched off there.

Variables

Use these SCSS variables to customize switch icons. The default values are:

$switch-icon-size: var(--icon-size);
// WCAG 2.5.8 minimum target size; the icon stays at $switch-icon-size, centered
$switch-icon-min-size: 1.5rem;
$switch-icon-disabled-opacity: $btn-disabled-opacity;
$switch-icon-loading-size: $spinner-width-sm;
$switch-icon-loading-border-width: $spinner-border-width-sm;
$switch-icon-loading-animation-speed: $spinner-animation-speed;

Class reference

Every class this component ships, grouped by what it changes. A name in braces stands for a family — {color} is any base color, {breakpoint} any responsive step.

switch-icon componentButton that swaps between two icons
switch-icon-a partIcon shown in the off state
switch-icon-b partIcon shown in the on state
switch-icon-fade behaviorCrossfades between the icons
switch-icon-flip behaviorFlips the icon over
switch-icon-scale behaviorScales one icon out and the other in
switch-icon-slide-{direction} behaviorSlides the icons; up, down, left, right, start or end
active stateSwitched on; Tabler toggles it on click
switch-icon-loading stateSpinner instead of the icons, clicks ignored

CSS

Variables

The component uses local CSS variables for real-time customization. Values for the CSS variables are set via Sass, so Sass customization is still supported, too. Source: core/scss/ui/_switch-icon.scss.

--switch-icon-size: #{$switch-icon-size};
--switch-icon-min-size: #{$switch-icon-min-size};
--switch-icon-disabled-opacity: #{$switch-icon-disabled-opacity};
--switch-icon-loading-size: #{$switch-icon-loading-size};
--switch-icon-loading-border-width: #{$switch-icon-loading-border-width};
--switch-icon-loading-animation-speed: #{$switch-icon-loading-animation-speed};

Sass variables

Override these variables before importing Tabler to change the defaults. Source: core/scss/_variables.scss.

$switch-icon-size: var(--icon-size);
$switch-icon-min-size: 1.5rem;
$switch-icon-disabled-opacity: $btn-disabled-opacity;
$switch-icon-loading-size: $spinner-width-sm;
$switch-icon-loading-border-width: $spinner-border-width-sm;
$switch-icon-loading-animation-speed: $spinner-animation-speed;