feat: update mobile nav to be accessible

Put 'Open Menu' button under nav tag. Add aria-label, aria-expanded and aria-controls in 'Open Menu'
button. Make the entire nav to be more accessible.
This commit is contained in:
satnaing
2022-12-06 22:48:15 +06:30
parent 93e67bf2be
commit 46ea4aa49a
+96 -75
View File
@@ -31,66 +31,76 @@ const { activeNav } = Astro.props;
) )
} }
</a> </a>
<button class="hamburger-menu" aria-label="menu"> <nav id="nav-menu">
<div class="icon-container flex"> <button
<div id="first-line"></div> class="hamburger-menu focus-outline"
<div id="second-line"></div> aria-label="Open Menu"
<div id="third-line"></div> aria-expanded="false"
</div> aria-controls="menu-items"
</button>
</div>
<nav class="display-none sm:flex">
<ul>
<li>
<a href="/posts" class={activeNav === "posts" ? "active" : ""}
>Posts</a
>
</li>
<li>
<a href="/tags" class={activeNav === "tags" ? "active" : ""}>Tags</a>
</li>
<li>
<a href="/about" class={activeNav === "about" ? "active" : ""}
>About</a
>
</li>
</ul>
<div class="button-wrapper">
<LinkButton
href="/search"
className={`focus-outline p-3 sm:p-1 ${
activeNav === "search" ? "active" : ""
}`}
ariaLabel="search"
title="Search"
> >
<svg xmlns="http://www.w3.org/2000/svg" class="scale-125 sm:scale-100" <div class="icon-container flex">
><path <div id="first-line"></div>
d="M19.023 16.977a35.13 35.13 0 0 1-1.367-1.384c-.372-.378-.596-.653-.596-.653l-2.8-1.337A6.962 6.962 0 0 0 16 9c0-3.859-3.14-7-7-7S2 5.141 2 9s3.14 7 7 7c1.763 0 3.37-.66 4.603-1.739l1.337 2.8s.275.224.653.596c.387.363.896.854 1.384 1.367l1.358 1.392.604.646 2.121-2.121-.646-.604c-.379-.372-.885-.866-1.391-1.36zM9 14c-2.757 0-5-2.243-5-5s2.243-5 5-5 5 2.243 5 5-2.243 5-5 5z" <div id="second-line"></div>
></path> <div id="third-line"></div>
</svg> </div>
</LinkButton> </button>
<ul id="menu-items" class="display-none sm:flex">
{ <li>
SITE.lightAndDarkMode && ( <a href="/posts" class={activeNav === "posts" ? "active" : ""}>
<button Posts
id="theme-btn" </a>
class="focus-outline" </li>
title="Toggles light & dark" <li>
aria-label="auto" <a href="/tags" class={activeNav === "tags" ? "active" : ""}>
aria-live="polite" Tags
</a>
</li>
<li>
<a href="/about" class={activeNav === "about" ? "active" : ""}>
About
</a>
</li>
<li>
<LinkButton
href="/search"
className={`focus-outline p-3 sm:p-1 ${
activeNav === "search" ? "active" : ""
}`}
ariaLabel="search"
title="Search"
> >
<svg xmlns="http://www.w3.org/2000/svg" id="moon-svg"> <svg
<path d="M20.742 13.045a8.088 8.088 0 0 1-2.077.271c-2.135 0-4.14-.83-5.646-2.336a8.025 8.025 0 0 1-2.064-7.723A1 1 0 0 0 9.73 2.034a10.014 10.014 0 0 0-4.489 2.582c-3.898 3.898-3.898 10.243 0 14.143a9.937 9.937 0 0 0 7.072 2.93 9.93 9.93 0 0 0 7.07-2.929 10.007 10.007 0 0 0 2.583-4.491 1.001 1.001 0 0 0-1.224-1.224zm-2.772 4.301a7.947 7.947 0 0 1-5.656 2.343 7.953 7.953 0 0 1-5.658-2.344c-3.118-3.119-3.118-8.195 0-11.314a7.923 7.923 0 0 1 2.06-1.483 10.027 10.027 0 0 0 2.89 7.848 9.972 9.972 0 0 0 7.848 2.891 8.036 8.036 0 0 1-1.484 2.059z" /> xmlns="http://www.w3.org/2000/svg"
class="scale-125 sm:scale-100"
><path
d="M19.023 16.977a35.13 35.13 0 0 1-1.367-1.384c-.372-.378-.596-.653-.596-.653l-2.8-1.337A6.962 6.962 0 0 0 16 9c0-3.859-3.14-7-7-7S2 5.141 2 9s3.14 7 7 7c1.763 0 3.37-.66 4.603-1.739l1.337 2.8s.275.224.653.596c.387.363.896.854 1.384 1.367l1.358 1.392.604.646 2.121-2.121-.646-.604c-.379-.372-.885-.866-1.391-1.36zM9 14c-2.757 0-5-2.243-5-5s2.243-5 5-5 5 2.243 5 5-2.243 5-5 5z"
></path>
</svg> </svg>
<svg xmlns="http://www.w3.org/2000/svg" id="sun-svg"> </LinkButton>
<path d="M6.993 12c0 2.761 2.246 5.007 5.007 5.007s5.007-2.246 5.007-5.007S14.761 6.993 12 6.993 6.993 9.239 6.993 12zM12 8.993c1.658 0 3.007 1.349 3.007 3.007S13.658 15.007 12 15.007 8.993 13.658 8.993 12 10.342 8.993 12 8.993zM10.998 19h2v3h-2zm0-17h2v3h-2zm-9 9h3v2h-3zm17 0h3v2h-3zM4.219 18.363l2.12-2.122 1.415 1.414-2.12 2.122zM16.24 6.344l2.122-2.122 1.414 1.414-2.122 2.122zM6.342 7.759 4.22 5.637l1.415-1.414 2.12 2.122zm13.434 10.605-1.414 1.414-2.122-2.122 1.414-1.414z" /> </li>
</svg> <li>
</button> {
) SITE.lightAndDarkMode && (
} <button
</div> id="theme-btn"
</nav> class="focus-outline"
title="Toggles light & dark"
aria-label="auto"
aria-live="polite"
>
<svg xmlns="http://www.w3.org/2000/svg" id="moon-svg">
<path d="M20.742 13.045a8.088 8.088 0 0 1-2.077.271c-2.135 0-4.14-.83-5.646-2.336a8.025 8.025 0 0 1-2.064-7.723A1 1 0 0 0 9.73 2.034a10.014 10.014 0 0 0-4.489 2.582c-3.898 3.898-3.898 10.243 0 14.143a9.937 9.937 0 0 0 7.072 2.93 9.93 9.93 0 0 0 7.07-2.929 10.007 10.007 0 0 0 2.583-4.491 1.001 1.001 0 0 0-1.224-1.224zm-2.772 4.301a7.947 7.947 0 0 1-5.656 2.343 7.953 7.953 0 0 1-5.658-2.344c-3.118-3.119-3.118-8.195 0-11.314a7.923 7.923 0 0 1 2.06-1.483 10.027 10.027 0 0 0 2.89 7.848 9.972 9.972 0 0 0 7.848 2.891 8.036 8.036 0 0 1-1.484 2.059z" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" id="sun-svg">
<path d="M6.993 12c0 2.761 2.246 5.007 5.007 5.007s5.007-2.246 5.007-5.007S14.761 6.993 12 6.993 6.993 9.239 6.993 12zM12 8.993c1.658 0 3.007 1.349 3.007 3.007S13.658 15.007 12 15.007 8.993 13.658 8.993 12 10.342 8.993 12 8.993zM10.998 19h2v3h-2zm0-17h2v3h-2zm-9 9h3v2h-3zm17 0h3v2h-3zM4.219 18.363l2.12-2.122 1.415 1.414-2.12 2.122zM16.24 6.344l2.122-2.122 1.414 1.414-2.122 2.122zM6.342 7.759 4.22 5.637l1.415-1.414 2.12 2.122zm13.434 10.605-1.414 1.414-2.122-2.122 1.414-1.414z" />
</svg>
</button>
)
}
</li>
</ul>
</nav>
</div>
</div> </div>
<Hr /> <Hr />
</header> </header>
@@ -103,38 +113,44 @@ const { activeNav } = Astro.props;
@apply max-w-3xl mx-auto flex flex-col sm:flex-row justify-between items-center; @apply max-w-3xl mx-auto flex flex-col sm:flex-row justify-between items-center;
} }
.top-nav-wrap { .top-nav-wrap {
@apply w-full p-4 sm:py-8 flex justify-between items-center; @apply relative w-full p-4 sm:py-8 flex justify-between items-start sm:items-center;
} }
.logo { .logo {
@apply font-semibold text-xl sm:text-2xl py-1; @apply absolute sm:static font-semibold text-xl sm:text-2xl py-1;
} }
.hamburger-menu { .hamburger-menu {
@apply p-2 sm:hidden; @apply self-end p-2 sm:hidden;
} }
.hamburger-menu svg { .hamburger-menu svg {
@apply fill-skin-base w-6 h-6 scale-125; @apply fill-skin-base w-6 h-6 scale-125;
} }
nav { nav {
@apply w-full py-2 sm:py-0 sm:pr-4 flex flex-col items-center sm:justify-end sm:flex-row sm:space-x-4 bg-skin-fill; @apply w-full sm:py-0 sm:ml-2 flex flex-col items-center sm:justify-end sm:flex-row sm:space-x-4 bg-skin-fill;
} }
nav ul { nav ul {
@apply flex flex-col sm:flex-row sm:space-x-4; @apply mt-4 w-44 grid grid-rows-4 grid-cols-2 gap-y-2 gap-x-2 sm:gap-y-0 sm:mt-0 sm:ml-0 sm:w-auto sm:gap-x-5;
} }
nav li { nav ul li {
@apply py-3 sm:py-2 text-center my-1 sm:my-0; @apply col-span-2 flex justify-center items-center;
} }
nav a { nav ul li a {
@apply px-6 py-3 sm:py-2 sm:px-3 font-medium hover:text-skin-accent; @apply px-4 py-3 w-full text-center sm:px-2 sm:py-1 sm:my-0 font-medium hover:text-skin-accent;
}
nav ul li:nth-child(4) a {
@apply w-auto;
}
nav ul li:nth-child(4),
nav ul li:nth-child(5) {
@apply col-span-1;
} }
nav a.active { nav a.active {
@apply underline underline-offset-4 decoration-wavy decoration-2; @apply underline underline-offset-4 decoration-wavy decoration-2;
} }
.button-wrapper { nav a.active svg {
@apply flex my-2 sm:my-0 space-x-4;
}
.button-wrapper a.active svg {
@apply fill-skin-accent; @apply fill-skin-accent;
} }
nav button { nav button {
@apply p-1; @apply p-1;
} }
@@ -168,16 +184,19 @@ const { activeNav } = Astro.props;
<script> <script>
// Toggle menu // Toggle menu
const menuBtn = document.querySelector(".hamburger-menu"); const menuBtn = document.querySelector(".hamburger-menu");
const navClassList = document.querySelector("nav")?.classList; const menuItems = document.querySelector("#menu-items")?.classList;
const iconContainer = document.querySelector(".icon-container")?.classList; const iconContainer = document.querySelector(".icon-container")?.classList;
const firstLine = document.querySelector("#first-line")?.classList; const firstLine = document.querySelector("#first-line")?.classList;
const secondLine = document.querySelector("#second-line ")?.classList; const secondLine = document.querySelector("#second-line ")?.classList;
const thirdLine = document.querySelector("#third-line")?.classList; const thirdLine = document.querySelector("#third-line")?.classList;
menuBtn!.addEventListener("click", function () { menuBtn!.addEventListener("click", function (event) {
if (navClassList?.contains("display-none")) { const menuExpanded = menuBtn?.getAttribute("aria-expanded");
navClassList?.remove("display-none"); if (menuExpanded === "false") {
menuBtn?.setAttribute("aria-expanded", "true");
menuBtn?.setAttribute("aria-label", "Close Menu");
menuItems?.remove("display-none");
// icon animation // icon animation
iconContainer?.remove("flex"); iconContainer?.remove("flex");
@@ -186,7 +205,9 @@ const { activeNav } = Astro.props;
thirdLine?.add("display-none"); thirdLine?.add("display-none");
secondLine?.add("!w-full", "-rotate-45", "absolute", "bottom-1/2"); secondLine?.add("!w-full", "-rotate-45", "absolute", "bottom-1/2");
} else { } else {
navClassList?.add("display-none"); menuBtn?.setAttribute("aria-expanded", "false");
menuBtn?.setAttribute("aria-label", "Open Menu");
menuItems?.add("display-none");
// icon animation // icon animation
iconContainer?.add("flex"); iconContainer?.add("flex");