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',...