Social Sharing Toolbar

I am a focusable link!
This is an example of a toolbar in which we have applied toolbar keyboard logic, allowing users to arrow-key within the toolbar.

HTML Source Code

<a href="#">I am a focusable link!</a>
<div id="social-toolbar" role="toolbar" tabindex="-1" aria-label="Share on Social Media" accesskey="s">
  <ul>
    <li>
      <button id="twitter" tabindex="0" aria-setsize="4" aria-posinset="1">
        <i class="fa fa-twitter-square">
          <span class="clipper">Twitter</span>
        </i>

      </button>
    </li>
    <li>
      <button id="facebook" tabindex="-1" aria-setsize="4" aria-posinset="2">
        <i class="fa fa-facebook-square">
          <span class="clipper">Facebook</span>
        </i>

      </button>
    </li>
    <li>
      <button id="linked-in" tabindex="-1" aria-setsize="4" aria-posinset="3">
        <i class="fa fa-linkedin-square">
          <span class="clipper">LinkedIn</span>
        </i>

      </button>
    </li>
    <li>
      <button id="google-plus" tabindex="-1" aria-setsize="4" aria-posinset="4">
        <i class="fa fa-google-plus-square">
          <span class="clipper">Google Plus</span>
        </i>

      </button>
    </li>
  </ul>
</div>
<div id="hidden-share" style="display: none;">
  Share Page
</div>

JavaScript Source Code

Dependencies:

  • JQuery
var $toolbar = $('#social-toolbar');
var $items = $toolbar.find('li');
$toolbar.on('keydown', 'button', function (e) {
  var which = e.which;
  var target = e.target;

  if (which === 37 || which === 38) { // LEFT |or| UP
    focusAdjacentItem(target, which, $items);
  } else if (which === 39 || which === 40) { // RIGHT |or| DOWN
    focusAdjacentItem(target, which, $items);
  }
});

/**
 * Focuses the adjacent item in the toolbar
 * @param  {HTMLElement} element   The target of the keyboard event
 * @param  {Integer} keystroke     The keycode
 * @param  {Object} $items         The jQuery object of items in the toolbar (array-like)
 */
function focusAdjacentItem(element, keystroke, $items) {
  var dir = (keystroke === 37 || keystroke === 38) ? 'prev' : 'next';
  var $li = $(element).closest('li');
  var $adjacentLi = (dir === 'next') ?
                    $li.next().first() :
                    $li.prev().first();
  if (!$adjacentLi[0]) {
    if (dir === 'next') {
      // there wasn't a found adjacent sibling
      // so let's go from the last to the first
      $adjacentLi = $($items[0]);
    } else {
      // there wasn't a found adjacent sibling
      // so let's go from the first to the last
      $adjacentLi = $($items[$items.length - 1]);
    }
  }
  var adjacentBtn = $adjacentLi.find('button')[0];

  if (adjacentBtn) {
    adjacentBtn.focus();
    adjacentBtn.tabIndex = 0; // make the "active" button the natively focusable aspect
    element.tabIndex = -1;
  }
}


/// Access Key ///
$(document.body).on('keydown', function (keyVent) {
  // access keys involve the alt key
  if (!keyVent.altKey) {
    return;
  }

  // s
  if (keyVent.which === 83) {
    keyVent.preventDefault();
    $toolbar.focus();
  }
});

// iOS specific fix:
// Applies aria-describedby="hidden-share" so the display: none
// message "Share Page" is read out as help text
var iOS = (navigator.userAgent.match(/(iPad|iPhone|iPod)/g) ? true : false );
if (iOS) {
  $('#social-toolbar button').each(function () {
    this.setAttribute('aria-describedby', 'hidden-share');
  });
}

CSS Source Code

#social-toolbar {
  position: absolute;
  top: 0;
  right: 0;
}

#social-toolbar ul {
  margin: 0;
  padding: 0;
}

#social-toolbar li {
  display: inline-block;
}

#social-toolbar button {
  font-size: 28px;
  background-color: #00539B;
  color: #fff;
  border: none;
}

#social-toolbar button:focus,
#social-toolbar button:hover {
  background-color: #fff;
  color: #00539B;
  outline: 2px solid #00539B;
}

.clipper {
  position: absolute;
  clip: rect(1px 1px 1px 1px);
  clip: rect(1px, 1px, 1px, 1px);
  width: 1px;
  height: 1px;
  overflow: hidden;
}

Copy and Paste Full Page Example