Skip to content

Commit b33a87c

Browse files
Merge pull request #48 from agilecollective/feature/jump-menu
Jump menu component.
2 parents 7fc8b2e + 110d461 commit b33a87c

File tree

7 files changed

+180
-1
lines changed

7 files changed

+180
-1
lines changed

src/assets/svg/chevron-circle.svg

Lines changed: 4 additions & 0 deletions
Loading

src/js/components/header/header.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,12 @@
4848
}
4949

5050
document.addEventListener("DOMContentLoaded", function () {
51+
const mobileNavWrapper = document.querySelector(".js-iati-mobile-nav");
52+
if (!mobileNavWrapper) {
53+
return;
54+
}
5155
const iatiMobileNav = new IatiMobileNav(
52-
document.querySelector(".js-iati-mobile-nav"),
56+
mobileNavWrapper,
5357
"iati-mobile-nav--open",
5458
);
5559

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* @file attaches jump menu visibility toggler.
3+
*/
4+
(function () {
5+
const toggleMenuMenuItemsVisibility = (
6+
isHidden,
7+
jumpMenuItems,
8+
jumpMenuToggle,
9+
) => {
10+
if (isHidden) {
11+
jumpMenuItems.removeAttribute("aria-hidden");
12+
jumpMenuToggle.setAttribute("aria-expanded", "true");
13+
} else {
14+
jumpMenuItems.setAttribute("aria-hidden", "true");
15+
jumpMenuToggle.setAttribute("aria-expanded", "false");
16+
}
17+
};
18+
document.addEventListener("DOMContentLoaded", () => {
19+
const jumpMenuItems = document.querySelector(".js-jump-menu-items");
20+
const jumpMenuToggle = document.querySelector(".js-jump-menu-toggle");
21+
if (jumpMenuItems && jumpMenuToggle) {
22+
toggleMenuMenuItemsVisibility(false, jumpMenuItems, jumpMenuToggle);
23+
jumpMenuToggle.addEventListener("click", () => {
24+
const isHidden = jumpMenuItems.getAttribute("aria-hidden");
25+
toggleMenuMenuItemsVisibility(isHidden, jumpMenuItems, jumpMenuToggle);
26+
});
27+
}
28+
});
29+
})();

src/js/main.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
import "./components/header/header.js";
2+
import "./components/jump-menu/jump-menu.js";

src/scss/components/_index.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
@forward "country-switcher/country-switcher";
77
@forward "piped-list/piped-list";
88
@forward "icon/icon";
9+
@forward "jump-menu/jump-menu";
910
@forward "search-bar/search-bar";
1011
@forward "table/table";
1112
@forward "menu-toggle/menu-toggle";
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
@use "../../tokens/color" as *;
2+
@use "../../tokens/spacing" as *;
3+
@use "../../tokens/screens" as *;
4+
5+
.iati-jump-menu {
6+
max-width: 30rem;
7+
&__header {
8+
background-color: $color-green-30;
9+
padding: 0.5rem 1rem;
10+
display: flex;
11+
align-items: center;
12+
justify-content: space-between;
13+
@media (min-width: $screen-md) {
14+
background: none;
15+
padding: 0 0 0.5rem;
16+
}
17+
}
18+
&__toggle {
19+
background-color: transparent;
20+
border: none;
21+
font-weight: 500;
22+
display: flex;
23+
align-items: center;
24+
gap: 0.5em;
25+
&::after {
26+
content: "";
27+
display: block;
28+
background-image: url("@assets/svg/chevron-circle.svg");
29+
background-repeat: no-repeat;
30+
width: 1.43rem;
31+
height: 1.43rem;
32+
background-size: contain;
33+
transform-origin: 50% 50%;
34+
transition: all 0.2s;
35+
}
36+
&[aria-expanded="true"] {
37+
&::after {
38+
transform: rotate(180deg);
39+
}
40+
}
41+
@media (min-width: $screen-md) {
42+
display: none;
43+
}
44+
}
45+
&__title {
46+
text-transform: uppercase;
47+
color: $color-grey-90;
48+
font-size: 0.9375rem;
49+
}
50+
&__items {
51+
list-style-type: none;
52+
padding: 1rem;
53+
margin: 0;
54+
display: block;
55+
transition: all 0.25s;
56+
transition-behavior: allow-discrete;
57+
opacity: 1;
58+
@starting-style {
59+
opacity: 0;
60+
}
61+
&[aria-hidden="true"] {
62+
display: none;
63+
opacity: 0;
64+
@media (min-width: $screen-md) {
65+
display: block;
66+
opacity: 1;
67+
}
68+
}
69+
@media (min-width: $screen-md) {
70+
box-shadow: none;
71+
padding: 0;
72+
}
73+
}
74+
&__item {
75+
border-inline-start: 4px solid $color-green-30;
76+
line-height: 1;
77+
padding: 0.4em;
78+
transition: all 0.2s ease-in-out;
79+
&:hover {
80+
background-color: $color-green-20;
81+
border-color: $color-teal-90;
82+
}
83+
}
84+
&__link {
85+
display: block;
86+
text-transform: uppercase;
87+
text-decoration: none;
88+
color: $color-teal-90;
89+
font-size: 0.75rem;
90+
font-weight: 800;
91+
line-height: 1.5;
92+
}
93+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import type { Meta, StoryObj } from "@storybook/web-components";
2+
import { html } from "lit";
3+
4+
const meta: Meta = {
5+
title: "Components/Jump Menu",
6+
parameters: {},
7+
};
8+
9+
const items = [
10+
"Page summary",
11+
"Narrative",
12+
"Assessment",
13+
"Exceptions",
14+
"comparison with original global partnership indicator methodology",
15+
"Pseudocode",
16+
];
17+
18+
export default meta;
19+
type Story = StoryObj;
20+
21+
export const Default: Story = {
22+
render: () => html`
23+
<nav class="iati-jump-menu">
24+
<div class="iati-jump-menu__header">
25+
<h2 class="iati-jump-menu__title">Jump to section</h2>
26+
<button
27+
class="iati-jump-menu__toggle js-jump-menu-toggle"
28+
aria-controls="iati-jump-menu-items"
29+
aria-expanded="true"
30+
>
31+
Open
32+
</button>
33+
</div>
34+
<ul
35+
id="iati-jump-menu-items"
36+
class="iati-jump-menu__items js-jump-menu-items"
37+
>
38+
${items.map(
39+
(i) =>
40+
html`<li class="iati-jump-menu__item">
41+
<a href="#" class="iati-jump-menu__link">${i}</a>
42+
</li>`,
43+
)}
44+
</ul>
45+
</nav>
46+
`,
47+
};

0 commit comments

Comments
 (0)