dropdown take one needs review

This commit is contained in:
2026-01-02 17:17:35 -08:00
parent 7a88b06c95
commit 0e561c888a
6 changed files with 216 additions and 52 deletions

View File

@ -15,18 +15,18 @@
<meta property="og:description" content="card one's travels | siblinghood of the traveling greeting card" /> <meta property="og:description" content="card one's travels | siblinghood of the traveling greeting card" />
<meta property="og:image" content="/img/logo-light.png" /> <meta property="og:image" content="/img/logo-light.png" />
<meta property="og:image:alt" content="blue and gold icon showing a greeting card with wings" /> <meta property="og:image:alt" content="blue and gold icon showing a greeting card with wings" />
<!-- CSS --> <!-- CSS -->
<link rel="stylesheet" href="/styles/main.css"> <link rel="stylesheet" href="/styles/main.css">
<link rel="stylesheet" href="/styles/cards.css"> <link rel="stylesheet" href="/styles/cards.css">
<link rel="stylesheet" href="/styles/nav.css">
<!-- JS -->
<script src="/scripts/nav.js" defer></script>
</head> </head>
<body> <body>
<header> <header>
<nav> <nav id="top-nav"><!-- auto populated by nav.js --></nav>
<ul>
<li><a href="/">home</a></li>
<li><a href="/card-two">card two</a></li>
</ul>
</nav>
<img id="logo-light" src="/img/logo-light.png" alt="blue and gold icon showing a greeting card with wings" /> <img id="logo-light" src="/img/logo-light.png" alt="blue and gold icon showing a greeting card with wings" />
<img id="logo-dark" src="/img/logo-dark.png" alt="blue and gold icon showing a greeting card with wings" /> <img id="logo-dark" src="/img/logo-dark.png" alt="blue and gold icon showing a greeting card with wings" />

View File

@ -15,18 +15,18 @@
<meta property="og:description" content="card two's travels | siblinghood of the traveling greeting card" /> <meta property="og:description" content="card two's travels | siblinghood of the traveling greeting card" />
<meta property="og:image" content="/img/logo-light.png" /> <meta property="og:image" content="/img/logo-light.png" />
<meta property="og:image:alt" content="blue and gold icon showing a greeting card with wings" /> <meta property="og:image:alt" content="blue and gold icon showing a greeting card with wings" />
<!-- CSS --> <!-- CSS -->
<link rel="stylesheet" href="/styles/main.css"> <link rel="stylesheet" href="/styles/main.css">
<link rel="stylesheet" href="/styles/cards.css"> <link rel="stylesheet" href="/styles/cards.css">
<link rel="stylesheet" href="/styles/nav.css">
<!-- JS -->
<script src="/scripts/nav.js" defer></script>
</head> </head>
<body> <body>
<header> <header>
<nav> <nav id="top-nav"><!-- auto populated by nav.js --></nav>
<ul>
<li><a href="/">home</a></li>
<li><a href="/card-one">card one</a></li>
</ul>
</nav>
<img id="logo-light" src="/img/logo-light.png" alt="blue and gold icon showing a greeting card with wings" /> <img id="logo-light" src="/img/logo-light.png" alt="blue and gold icon showing a greeting card with wings" />
<img id="logo-dark" src="/img/logo-dark.png" alt="blue and gold icon showing a greeting card with wings" /> <img id="logo-dark" src="/img/logo-dark.png" alt="blue and gold icon showing a greeting card with wings" />

View File

@ -15,17 +15,17 @@
<meta property="og:description" content="Siblinghood of the Traveling Greeting Card" /> <meta property="og:description" content="Siblinghood of the Traveling Greeting Card" />
<meta property="og:image" content="/img/logo-light.png" /> <meta property="og:image" content="/img/logo-light.png" />
<meta property="og:image:alt" content="blue and gold icon showing a greeting card with wings" /> <meta property="og:image:alt" content="blue and gold icon showing a greeting card with wings" />
<!-- CSS --> <!-- CSS -->
<link rel="stylesheet" href="/styles/main.css"> <link rel="stylesheet" href="/styles/main.css">
<link rel="stylesheet" href="/styles/nav.css">
<!-- JS -->
<script src="/scripts/nav.js" defer></script>
</head> </head>
<body> <body>
<header> <header>
<nav> <nav id="top-nav"><!-- auto populated by nav.js --></nav>
<ul>
<li><a href="/card-one">card one</a></li>
<li><a href="/card-two">card two</a></li>
</ul>
</nav>
<img id="logo-light" src="/img/logo-light.png" alt="blue and gold icon showing a greeting card with wings" /> <img id="logo-light" src="/img/logo-light.png" alt="blue and gold icon showing a greeting card with wings" />
<img id="logo-dark" src="/img/logo-dark.png" alt="blue and gold icon showing a greeting card with wings" /> <img id="logo-dark" src="/img/logo-dark.png" alt="blue and gold icon showing a greeting card with wings" />

122
scripts/nav.js Normal file
View File

@ -0,0 +1,122 @@
/* Nav construction */
const cards = [
{
title: "card one",
href: "/card-one/"
},
{
title: "card two",
href: "/card-two/"
}
]
const constructMenuLink = function(title, href) {
const path = window.location.pathname;
const a = document.createElement("a");
a.href = href;
a.title = title;
a.innerHTML = title;
if (path === href) a.id = "current-page";
return a;
}
const constructDropdown = function() {
const div = document.createElement("div");
div.id = "dropdown";
const button = document.createElement("button");
button.innerHTML = "cards ⮷";
button.id="drop-button";
button.ariaLabel = "card submenu";
button.ariaExpanded = "false";
button.setAttribute("aria-controls", "drop-content");
div.append(button);
const ul = document.createElement("ul");
ul.id = "drop-content";
ul.ariaHidden = "true";
for (const card of cards) {
const li = document.createElement("li");
li.append(constructMenuLink(card.title, card.href));
ul.append(li);
}
div.append(ul);
return div;
}
const constructNav = function() {
const nav = document.getElementById("top-nav");
nav.append(constructMenuLink("home", "/"));
nav.append(constructDropdown());
}
constructNav();
/* Dropdown handling */
const dropdown = document.getElementById("dropdown");
const dropdownButton = document.getElementById("drop-button");
const dropdownContent = document.getElementById("drop-content");
const dropdownItems = dropdownContent.querySelectorAll("a");
const firstDropdownItem = dropdownItems[0];
const lastDropdownItem = dropdownItems[dropdownItems.length - 1];
const openDropdown = function() {
dropdownContent.classList.add("show");
dropdownContent.setAttribute("aria-hidden", "false");
dropdownButton.setAttribute("aria-expanded", "true");
}
const closeDropdown = function() {
if (dropdownButton.ariaExpanded === "true") {
dropdownContent.classList.remove("show");
dropdownContent.setAttribute("aria-hidden", "true");
dropdownButton.setAttribute("aria-expanded", "false");
/* focus the button again */
dropdownButton.focus();
}
}
dropdownButton.addEventListener("click", (event) => {
if (dropdownButton.ariaExpanded === "false") openDropdown();
else closeDropdown();
});
dropdownButton.addEventListener("keydown", (event) => {
if (event.key === "Enter" || event.key === " ") { // Space or Enter key
event.preventDefault(); // Prevent the default action to stop scrolling when pressing Space
if (dropdownButton.ariaExpanded === "false") {
openDropdown();
} else {
closeDropdown();
}
}
});
firstDropdownItem.addEventListener("keydown", (event) => {
if (event.key === "Tab" && event.shiftKey) {
event.preventDefault();
closeDropdown();
}
});
lastDropdownItem.addEventListener("keydown", (event) => {
if (event.key === "Tab" && !event.shiftKey) {
event.preventDefault();
closeDropdown();
}
});
document.addEventListener("keydown", (event) => {
if (event.key === "Escape") closeDropdown();
});
window.addEventListener("click", (event) => {
if (!event.target.matches("#drop-button")) closeDropdown();
});

View File

@ -123,40 +123,9 @@ time {
font-weight: 700; font-weight: 700;
} }
nav ul { button {
display: flex; cursor: pointer;
gap: 1rem; background-color: var(--color-bg);
list-style: none;
justify-content: center;
margin: 1rem auto;
}
nav a {
font-size: 1.4rem;
border: 1px solid;
border-radius: .15rem;
padding: .15rem .3rem;
color: var(--color-accent);
text-decoration: none;
}
@media (max-width: 650px) {
nav a {
font-size: 1.1rem;
}
}
@media (any-hover: hover) {
nav a:hover {
color: var(--color-bg);
background-color: var(--color-accent);
}
}
nav a:focus-visible {
outline: none;
color: var(--color-bg);
background-color: var(--color-accent);
} }
header img { header img {

73
styles/nav.css Normal file
View File

@ -0,0 +1,73 @@
nav {
display: flex;
gap: 1rem;
justify-content: center;
margin: 1rem auto;
}
nav a,
nav button {
font-size: 1.4rem;
border: 1px solid;
border-radius: .15rem;
padding: .15rem .3rem;
color: var(--color-accent);
text-decoration: none;
line-height: 2rem;
}
@media (max-width: 650px) {
nav a {
font-size: 1.1rem;
}
}
@media (any-hover: hover) {
nav a:hover,
nav button:hover {
color: var(--color-bg);
background-color: var(--color-accent);
border-color: var(--color-accent);
}
}
nav a:focus-visible,
nav button:focus-visible {
outline: none;
color: var(--color-bg);
background-color: var(--color-accent);
border-color: var(--color-accent);
}
#current-page {
border-right-width: .5rem;
border-left-width: .5rem;
}
nav ul {
list-style: none;
display: none;
position: absolute;
z-index: 1;
margin: 0 0 0 1rem;
min-width: 8rem;
}
#dropdown {
position: relative;
display: inline-block;
min-width: 3rem;
}
nav ul.show {
display: block;
}
nav ul li {
margin: .25rem;
}
nav ul a {
display: inline-block;
background-color: var(--color-bg);
}