JSFiddle - React, Tailwind, and code Playground

by Hollie Szadowski

HTML

<h1>Testing losing focus</h1>
<p>
some text and a <a href="#">link</a>
</p>
<div class="test">
<button type="button" aria-expanded="false" aria-controls="faq1_desc">Test accordion</button>

<p id="faq1_desc" class="desc">
  <button class="close">close</button>
  Cats use postures and movement to communicate a wide range of information. There are various responses such as when cats arch their backs, erect their hairs and adopt a sideward posture to communicate fear or aggression. Others may be only a single behavioural change (as perceived by humans) such as slowly blinking to signal relaxation.

Domestic cats frequently use visual communication with their eyes, ears, mouths, tails, coats and body postures. It has been stated that a cat's facial features change the most and are probably the best indicator of cat communication.
  <button>
  inner tab stop
  </button>
</p>
</div>

<div class="test">
<button type="button" aria-expanded="false" aria-controls="faq3_desc">This one works</button>

<p id="faq3_desc" class="desc fixed">
  <button class="close">close</button>
  Cats use postures and movement to communicate a wide range of information. There are various responses such as when cats arch their backs, erect their hairs and adopt a sideward posture to communicate fear or aggression. Others may be only a single behavioural change (as perceived by humans) such as slowly blinking to signal relaxation.

Domestic cats frequently use visual communication with their eyes, ears, mouths, tails, coats and body postures. It has been stated that a cat's facial features change the most and are probably the best indicator of cat communication.
  <button>inner tab stop</button>
</p>
</div>

<div class="test">
<button type="button" aria-expanded="false" aria-controls="dialog">very simple dialog</button>

<p id="dialog" role="dialog" aria-modal="true" class="dialog">
  <button class="close">close</button>
  Cats use postures and movement to communicate a wide range of...

CSS

.dialog {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 1em;
  border: 2px solid #ccc;
  background: #fff;
}

.test {
  margin-bottom: 1em;
}

JavaScript

/*
*   This content is licensed according to the W3C Software License at
*   https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
*
*   File:   ButtonExpand.js
*
*   Desc:   Checkbox widget that implements ARIA Authoring Practices
*           for a menu of links
*/

/*
*   @constructor ButtonExpand
*
*
*/
var ButtonExpand = function (domNode) {
  this.domNode = domNode;
};

ButtonExpand.prototype.init = function () {

  this.controlledNode = false;

  var id = this.domNode.getAttribute('aria-controls');

  this.controlledNode = document.getElementById(id);
  this.closeButton = this.controlledNode.querySelector('.close');

  this.domNode.setAttribute('aria-expanded', 'false');
  this.hideContent(false);

  this.controlledNode.addEventListener('keydown', this.handleKeydown.bind(this));
  this.domNode.addEventListener('click', this.handleClick.bind(this));
  this.closeButton.addEventListener('click', this.handleClick.bind(this));
};

ButtonExpand.prototype.showContent = function () {
  if (this.controlledNode) {
    this.controlledNode.style.display = 'block';
  }
};

ButtonExpand.prototype.hideContent = function (setFocus = true) {

	if (setFocus && this.controlledNode.classList.contains('fixed')) {
  	this.domNode.focus();
  }

  if (this.controlledNode) {
    this.controlledNode.style.display = 'none';
  }

};

ButtonExpand.prototype.toggleExpand = function () {
  if (this.domNode.getAttribute('aria-expanded') === 'true') {
    this.domNode.setAttribute('aria-expanded', 'false');
    this.hideContent();
  }
  else {
    this.domNode.setAttribute('aria-expanded', 'true');
    this.showContent();
  }
};

/* EVENT HANDLERS */

ButtonExpand.prototype.handleKeydown = function (event) {
  if (event.key === 'Escape') {
    this.toggleExpand();
    event.stopPropagation();
    event.preventDefault();
  }
};

ButtonExpand.prototype.handleClick = function (event) {
  this.toggleExpand();
};

/* Initialize Hide/Show Buttons */

  var buttons = ...