JSFiddle - React, Tailwind, and code Playground

by uiwwnw

HTML

<nav class="menu" id="a11y-menu" role="navigation" aria-label="Main menu">
  <ul class="nav level-1 list-reset" role="menubar" aria-hidden="false">
    <li class="has-subnav" role="menuitem" aria-haspopup="true">
      <a href="#academy">아카데미</a>
      <ul class="level-2 list-reset" data-test="true" aria-hidden="true" role="menu">
        <li role="menuitem">
          <a href="#info" tabindex="-1">아카데미소개</a>
        </li>
        <li role="menuitem">
          <a href="#history" tabindex="-1">아카데미연혁</a>
        </li>
        <li role="menuitem">
          <a href="#manager" tabindex="-1">매니저소개</a>
        </li>
        <li role="menuitem">
          <a href="#map" tabindex="-1">오시는길</a>
        </li>
      </ul>
    </li>
    <li role="menuitem" aria-haspopup="true">
      <a href="#academy">취업과정</a>
      <ul class="level-2 list-reset" data-test="true" aria-hidden="true" role="menu" class="list-reset">
        <li role="menuitem">
          <a href="#strategy" tabindex="-1">국가기간전략산업</a>
        </li>
        <li role="menuitem">
          <a href="#card" tabindex="-1">계좌제</a>
        </li>
        <li role="menuitem">
          <a href="#core" tabindex="-1">핵심직무과정</a>
        </li>
        <li role="menuitem">
          <a href="#jobs" tabindex="-1">취업아카데미</a>
        </li>
      </ul>
    </li>
    <li role="menuitem" aria-haspopup="true">
      <a href="#story">아카데미Story</a>
      <ul class="level-2 list-reset" data-test="true" aria-hidden="true" role="menu" class="list-reset">
        <li role="menuitem">
          <a href="#techstory" tabindex="-1">기술스토리</a>
        </li>
        <li role="menuitem">
          <a href="#bookstory" tabindex="-1">책스토리</a>
        </li>
        <li role="menuitem">
          <a href="#studentstory" tabindex="-1">연수생스토리</a>
        </li>
      </ul>
    </li>
    <li role="menuitem" aria-haspopup="true">
      <a href="#customer">고객센터</a>
      <ul class="level-2 list-reset" data-test="true" aria-hidden="true" role="menu"...

CSS

.nav {
  float: left;
  margin: 20px 0;
}

.nav ul {
  position: absolute;
  top: 2.5em;
  left: -9999px;
  opacity: 0;
  transition: 0.1s linear opacity;
  min-width: 150px;
}

.nav li {
  float: left;
  position: relative;
}

.nav li>a {
  float: left;
  padding: 10px 15px;
  text-decoration: none;
}

.nav li>a:hover,
.nav li>a:focus,
.nav li:focus>a,
.nav li:hover>a {
  background: #EFEFEF;
  outline: 0;
}

.nav li:hover ul,
.nav li:focus ul,
ul.show-menu {
  left: 0;
  opacity: 0.99;
}

.nav ul li {
  float: none;
  position: static;
}

.nav ul a {
  float: none;
  display: block;
  font-size: 12px;
  text-shadow: none;
  transition: 0.1s linear all;
}

.nav ul a:hover,
.nav ul a:focus {
  text-shadow: none;
}

.list-reset {
  margin: 0;
  padding: 0;
  list-style: none;
}

JavaScript

$(document).ready(function() {
  $('.nav').setup_navigation();
  $('body').addClass('js');
  var $menu = $('#menu'),
    $menulink = $('.menu-link'),
    $menuTrigger = $('.has-subnav > a');
  $menulink.click(function(e) {
    e.preventDefault();
    $menulink.toggleClass('active');
    $menu.toggleClass('active');
  });
  $menuTrigger.click(function(e) {
    e.preventDefault();
    var $this = $(this);
    $this.toggleClass('active').next('ul').toggleClass('active');
  });
});
var keyCodeMap = {
  48: "0",
  49: "1",
  50: "2",
  51: "3",
  52: "4",
  53: "5",
  54: "6",
  55: "7",
  56: "8",
  57: "9",
  59: ";",
  65: "a",
  66: "b",
  67: "c",
  68: "d",
  69: "e",
  70: "f",
  71: "g",
  72: "h",
  73: "i",
  74: "j",
  75: "k",
  76: "l",
  77: "m",
  78: "n",
  79: "o",
  80: "p",
  81: "q",
  82: "r",
  83: "s",
  84: "t",
  85: "u",
  86: "v",
  87: "w",
  88: "x",
  89: "y",
  90: "z",
  96: "0",
  97: "1",
  98: "2",
  99: "3",
  100: "4",
  101: "5",
  102: "6",
  103: "7",
  104: "8",
  105: "9"
}
$.fn.setup_navigation = function(settings) {
  settings = jQuery.extend({
    menuHoverClass: 'show-menu',
  }, settings);
  // 현재 객체에는 role를 menubar로
  // li 객체에는 role를 menuitem으로 설정한다.
  $(this).attr('role', 'menubar').find('li').attr('role', 'menuitem');
  var top_level_links = $(this).find(' > li > a');
  // 모든 top-level링크는 tabindex="0"를 추가한다.
  // tabindex를 -1로 설정하면 top_level_links는 메뉴가 오픈될 때까지
  // 포커스를 받지 못한다.
  top_level_links.next('ul')
    .attr('data-test', 'true')
    .attr({
      'aria-hidden': 'true ',
      'role': 'menu'
    })
    .find('a')
    .attr('tabIndex', -1);
  // top_level_links 하위에 ul이 있다면 부모의 li 객체에
  // aria-haspopup를 true로 설정한다.
  top_level_links.each(function() {
    if ($(this).next('ul').length > 0)
      $(this).parent('li').attr('aria-haspopup', 'true');
  });
  top_level_links.hover(function() {
    $(this).closest('ul')
      // menu가 보이지 않으면 최상위 ul에
      // aria-hidden="false"를 추가한다.
      .attr('aria-hidden',...