|
9 | 9 | >
|
10 | 10 | <div class="max-w-screen-xl flex flex-wrap items-center justify-between mx-auto py-[30px]">
|
11 | 11 | <a
|
| 12 | + id="logo" |
12 | 13 | href="https://pressbooks.com/"
|
13 | 14 | title="Pressbooks Home Page"
|
14 | 15 | data-cy="return-home-button"
|
|
48 | 49 | class="hidden w-full lg:block lg:w-auto"
|
49 | 50 | >
|
50 | 51 | <ul class="font-medium flex items-start lg:items-center gap-4 flex-col p-4 lg:p-0 mt-4 border border-gray-100 rounded-lg bg-gray-50 lg:flex-row lg:mt-0 lg:border-0 lg:bg-white">
|
51 |
| - <li class="group relative"> |
| 52 | + <li |
| 53 | + class="group relative" |
| 54 | + role="menuitem" |
| 55 | + @mouseleave="hideSubmenu('products')" |
| 56 | + > |
52 | 57 | <a
|
53 | 58 | href="#"
|
| 59 | + aria-haspopup="true" |
| 60 | + aria-expanded="false" |
54 | 61 | class="flex gap-0.5 items-center py-2 pl-3 pr-4 text-pb-dark-blue rounded hover:bg-gray-100 lg:hover:bg-transparent lg:border-0 lg:hover:text-pb-red lg:p-0 font-semibold text-[18px]"
|
| 62 | + @keydown.enter.prevent="toggleSubmenu('products')" |
| 63 | + @keydown.space.prevent="toggleSubmenu('products')" |
| 64 | + @focus="showSubmenu('products')" |
| 65 | + @mouseover="!isTouchDevice.value && showSubmenu('products')" |
| 66 | + @keydown.shift.tab.prevent="closeAndFocusPrev('products')" |
| 67 | + @click.prevent="isTouchDevice.value && toggleSubmenu('products')" |
55 | 68 | >
|
56 | 69 | Products
|
57 | 70 | <span class="ml-1">
|
|
70 | 83 | </svg>
|
71 | 84 | </span>
|
72 | 85 | </a>
|
73 |
| - <!-- Dropdown menu --> |
74 |
| - <ul class="absolute hidden group-hover:block bg-white shadow-lg -mt-1 rounded-lg p-4 space-y-2 z-50 min-w-60"> |
75 |
| - <li> |
| 86 | + <ul |
| 87 | + v-show="isSubmenuVisible('products')" |
| 88 | + id="products" |
| 89 | + ref="products" |
| 90 | + class="absolute bg-white shadow-lg -mt-1 rounded-lg p-4 space-y-2 z-50 min-w-60" |
| 91 | + role="menu" |
| 92 | + > |
| 93 | + <li role="menuitem"> |
76 | 94 | <a
|
77 | 95 | href="https://pressbooks.com/enterprise/"
|
78 | 96 | class="text-gray-500 font-semibold text-[18px]"
|
| 97 | + @keydown.shift.tab.prevent="focusParent('products')" |
79 | 98 | >Enterprise</a>
|
80 | 99 | </li>
|
81 |
| - <li> |
| 100 | + <li role="menuitem"> |
82 | 101 | <a
|
83 | 102 | href="https://pressbooks.com/self-publisher/"
|
84 | 103 | class="text-gray-500 font-semibold text-[18px]"
|
85 | 104 | >Self-Publisher</a>
|
86 | 105 | </li>
|
87 |
| - <li> |
| 106 | + <li role="menuitem"> |
88 | 107 | <a
|
89 | 108 | href="/"
|
90 | 109 | class="text-gray-500 font-semibold text-[18px]"
|
| 110 | + @blur="hideSubmenu('products')" |
91 | 111 | >Pressbooks Directory</a>
|
92 | 112 | </li>
|
93 | 113 | </ul>
|
94 | 114 | </li>
|
95 |
| - <li class="group relative"> |
| 115 | + <li |
| 116 | + class="group relative" |
| 117 | + @mouseleave="hideSubmenu('plans')" |
| 118 | + > |
96 | 119 | <a
|
97 |
| - href="https://pressbooks.com/plans-pricing/" |
| 120 | + aria-haspopup="true" |
| 121 | + aria-expanded="false" |
| 122 | + href="#" |
98 | 123 | class="flex gap-0.5 items-center py-2 pl-3 pr-4 text-pb-dark-blue rounded hover:bg-gray-100 lg:hover:bg-transparent lg:border-0 lg:hover:text-pb-red lg:p-0 font-semibold text-[18px]"
|
| 124 | + @keydown.enter.prevent="toggleSubmenu('plans')" |
| 125 | + @keydown.space.prevent="toggleSubmenu('plans')" |
| 126 | + @focus="showSubmenu('plans')" |
| 127 | + @mouseover="!isTouchDevice.value && showSubmenu('plans')" |
| 128 | + @keydown.shift.tab.prevent="closeAndFocusPrev('plans')" |
| 129 | + @click.prevent="isTouchDevice.value && toggleSubmenu('plans')" |
99 | 130 | >
|
100 | 131 | Plans & Pricing
|
101 | 132 | <span class="ml-1">
|
|
114 | 145 | </svg>
|
115 | 146 | </span>
|
116 | 147 | </a>
|
117 |
| - <ul class="absolute hidden group-hover:block bg-white shadow-lg -mt-1 rounded-lg p-4 space-y-2 z-50 min-w-60"> |
118 |
| - <li> |
| 148 | + <ul |
| 149 | + v-show="isSubmenuVisible('plans')" |
| 150 | + id="plans" |
| 151 | + ref="plans" |
| 152 | + class="absolute group-hover:block bg-white shadow-lg -mt-1 rounded-lg p-4 space-y-2 z-50 min-w-60" |
| 153 | + role="menu" |
| 154 | + > |
| 155 | + <li role="menuitem"> |
119 | 156 | <a
|
120 | 157 | href="https://pressbooks.com/educational-institutions-plans-and-pricing/"
|
121 | 158 | class="text-gray-500 font-semibold text-[18px]"
|
| 159 | + @keydown.shift.tab.prevent="focusParent('plans')" |
122 | 160 | >Enterprise Networks</a>
|
123 | 161 | </li>
|
124 |
| - <li> |
| 162 | + <li role="menuitem"> |
125 | 163 | <a
|
126 | 164 | href="https://pressbooks.com/self-publisher-plans-and-pricing/"
|
127 | 165 | class="text-gray-500 font-semibold text-[18px]"
|
| 166 | + @blur="hideSubmenu('plans')" |
128 | 167 | >Self-Publisher Plans</a>
|
129 | 168 | </li>
|
130 | 169 | </ul>
|
131 | 170 | </li>
|
132 |
| - <li class="group relative"> |
| 171 | + <li |
| 172 | + class="group relative" |
| 173 | + @mouseleave="hideSubmenu('resources')" |
| 174 | + > |
133 | 175 | <a
|
| 176 | + aria-haspopup="true" |
| 177 | + aria-expanded="false" |
134 | 178 | href="#"
|
135 | 179 | class="flex gap-0.5 items-center py-2 pl-3 pr-4 text-pb-dark-blue rounded hover:bg-gray-100 lg:hover:bg-transparent lg:border-0 lg:hover:text-pb-red lg:p-0 font-semibold text-[18px]"
|
| 180 | + @keydown.enter.prevent="toggleSubmenu('resources')" |
| 181 | + @keydown.space.prevent="toggleSubmenu('resources')" |
| 182 | + @focus="showSubmenu('resources')" |
| 183 | + @mouseover="!isTouchDevice.value && showSubmenu('resources')" |
| 184 | + @keydown.shift.tab.prevent="closeAndFocusPrev('resources')" |
| 185 | + @click.prevent="isTouchDevice.value && toggleSubmenu('resources')" |
136 | 186 | >
|
137 | 187 | Resources
|
138 | 188 | <span class="ml-1">
|
|
151 | 201 | </svg>
|
152 | 202 | </span>
|
153 | 203 | </a>
|
154 |
| - <ul class="absolute hidden group-hover:block bg-white shadow-lg -mt-1 rounded-lg p-4 space-y-2 z-50 min-w-60"> |
155 |
| - <li> |
| 204 | + <ul |
| 205 | + v-show="isSubmenuVisible('resources')" |
| 206 | + id="resources" |
| 207 | + ref="resources" |
| 208 | + class="absolute group-hover:block bg-white shadow-lg -mt-1 rounded-lg p-4 space-y-2 z-50 min-w-60" |
| 209 | + role="menu" |
| 210 | + > |
| 211 | + <li role="menuitem"> |
156 | 212 | <a
|
157 | 213 | href="https://pressbooks.com/collections-hub/"
|
158 | 214 | class="text-gray-500 font-semibold text-[18px]"
|
| 215 | + @keydown.shift.tab.prevent="focusParent('resources')" |
159 | 216 | >Collections Hub</a>
|
160 | 217 | </li>
|
161 |
| - <li> |
| 218 | + <li role="menuitem"> |
162 | 219 | <a
|
163 | 220 | href="https://pressbooks.com/category/success-stories/"
|
164 | 221 | class="text-gray-500 font-semibold text-[18px]"
|
165 | 222 | >Success Stories</a>
|
166 | 223 | </li>
|
167 |
| - <li> |
| 224 | + <li role="menuitem"> |
168 | 225 | <a
|
169 | 226 | href="https://pressbooks.com/pressbooks-blog/"
|
170 | 227 | class="text-gray-500 font-semibold text-[18px]"
|
171 | 228 | >Blog</a>
|
172 | 229 | </li>
|
173 |
| - <li> |
| 230 | + <li role="menuitem"> |
174 | 231 | <a
|
175 | 232 | href="/"
|
176 | 233 | class="text-gray-500 font-semibold text-[18px]"
|
177 | 234 | >Pressbooks Directory</a>
|
178 | 235 | </li>
|
179 |
| - <li> |
| 236 | + <li role="menuitem"> |
180 | 237 | <a
|
181 | 238 | href="https://pressbooks.com/support/"
|
182 | 239 | class="text-gray-500 font-semibold text-[18px]"
|
183 | 240 | >Support Guides</a>
|
184 | 241 | </li>
|
185 |
| - <li> |
| 242 | + <li role="menuitem"> |
186 | 243 | <a
|
187 | 244 | href="https://pressbooks.com/webinars/"
|
188 | 245 | class="text-gray-500 font-semibold text-[18px]"
|
| 246 | + @blur="hideSubmenu('resources')" |
189 | 247 | >Events & Webinars</a>
|
190 | 248 | </li>
|
191 | 249 | </ul>
|
192 | 250 | </li>
|
193 |
| - <li class="group relative"> |
| 251 | + <li |
| 252 | + class="group relative" |
| 253 | + @mouseleave="hideSubmenu('about')" |
| 254 | + > |
194 | 255 | <a
|
195 |
| - href="https://pressbooks.com/about/" |
| 256 | + aria-haspopup="true" |
| 257 | + aria-expanded="false" |
| 258 | + href="#" |
196 | 259 | class="flex gap-0.5 items-center py-2 pl-3 pr-4 text-pb-dark-blue rounded hover:bg-gray-100 lg:hover:bg-transparent lg:border-0 lg:hover:text-pb-red lg:p-0 font-semibold text-[18px]"
|
| 260 | + @keydown.enter.prevent="toggleSubmenu('about')" |
| 261 | + @keydown.space.prevent="toggleSubmenu('about')" |
| 262 | + @focus="showSubmenu('about')" |
| 263 | + @mouseover="!isTouchDevice.value && showSubmenu('about')" |
| 264 | + @keydown.shift.tab.prevent="closeAndFocusPrev('about')" |
| 265 | + @click.prevent="isTouchDevice.value && toggleSubmenu('about')" |
197 | 266 | >
|
198 | 267 | About
|
199 | 268 | <span class="ml-1">
|
|
212 | 281 | </svg>
|
213 | 282 | </span>
|
214 | 283 | </a>
|
215 |
| - <ul class="absolute hidden group-hover:block bg-white shadow-lg -mt-1 rounded-lg p-4 space-y-2 z-50 min-w-60"> |
216 |
| - <li> |
| 284 | + <ul |
| 285 | + v-show="isSubmenuVisible('about')" |
| 286 | + id="about" |
| 287 | + ref="about" |
| 288 | + class="absolute group-hover:block bg-white shadow-lg -mt-1 rounded-lg p-4 space-y-2 z-50 min-w-60" |
| 289 | + role="menu" |
| 290 | + > |
| 291 | + <li role="menuitem"> |
217 | 292 | <a
|
218 | 293 | href="https://pressbooks.com/about/"
|
219 | 294 | class="text-gray-500 font-semibold text-[18px]"
|
| 295 | + @keydown.shift.tab.prevent="focusParent('about')" |
220 | 296 | >About Pressbooks</a>
|
221 | 297 | </li>
|
222 |
| - <li> |
| 298 | + <li role="menuitem"> |
223 | 299 | <a
|
224 | 300 | href="https://pressbooks.com/pressbooks-team/"
|
225 | 301 | class="text-gray-500 font-semibold text-[18px]"
|
226 | 302 | >Our Team</a>
|
227 | 303 | </li>
|
228 |
| - <li> |
| 304 | + <li role="menuitem"> |
229 | 305 | <a
|
230 | 306 | href="https://pressbooks.com/category/inside-pressbooks/"
|
231 | 307 | class="text-gray-500 font-semibold text-[18px]"
|
| 308 | + @blur="hideSubmenu('about')" |
232 | 309 | >Inside Pressbooks</a>
|
233 | 310 | </li>
|
234 | 311 | </ul>
|
235 | 312 | </li>
|
| 313 | + <!-- Request a Demo Button --> |
236 | 314 | <li class="lg:inline-block lg:text-center lg:border-2 lg:border-red-700 lg:text-white lg:bg-red-700 lg:rounded-full lg:leading-[20px] lg:ml-24">
|
237 | 315 | <a
|
238 | 316 | href="https://pressbooks.com/request-a-pressbooks-demo/"
|
|
246 | 324 | </header>
|
247 | 325 | </template>
|
248 | 326 |
|
249 |
| -<script> |
| 327 | +<script setup> |
| 328 | +import {ref, onMounted, onUnmounted} from 'vue'; |
| 329 | +
|
| 330 | +const isTouchDevice = ref(false); |
| 331 | +
|
| 332 | +onMounted(() => { |
| 333 | + isTouchDevice.value = 'ontouchstart' in window || navigator.maxTouchPoints > 0; |
| 334 | + window.addEventListener('keydown', handleKeydown); |
| 335 | +}); |
| 336 | +
|
| 337 | +onUnmounted(() => { |
| 338 | + window.removeEventListener('keydown', handleKeydown); |
| 339 | +}); |
| 340 | +
|
| 341 | +const submenus = ref({ |
| 342 | + products: false, |
| 343 | + plans: false, |
| 344 | + resources: false, |
| 345 | + about: false |
| 346 | +}); |
| 347 | +
|
| 348 | +const closeAllSubmenus = () => { |
| 349 | + Object.keys(submenus.value).forEach((key) => { |
| 350 | + submenus.value[key] = false; |
| 351 | + }); |
| 352 | +}; |
| 353 | +
|
| 354 | +const handleKeydown = (event) => { |
| 355 | + if (event.key === 'Escape') { |
| 356 | + closeAllSubmenus(); |
| 357 | + } |
| 358 | +}; |
| 359 | +
|
| 360 | +const isSubmenuVisible = (id) => { |
| 361 | + return submenus.value[id]; |
| 362 | +}; |
| 363 | +
|
| 364 | +const showSubmenu = (id) => { |
| 365 | + submenus.value[id] = true; |
| 366 | +}; |
| 367 | +
|
| 368 | +const hideSubmenu = (id) => { |
| 369 | + submenus.value[id] = false; |
| 370 | +}; |
| 371 | +
|
| 372 | +const toggleSubmenu = (id) => { |
| 373 | + submenus.value[id] = !submenus.value[id]; |
| 374 | +}; |
| 375 | +
|
| 376 | +const focusParent = (id) => { |
| 377 | + const parentMenu = document.querySelector(`#${id}`).previousElementSibling; |
| 378 | + if (parentMenu) { |
| 379 | + parentMenu.focus(); |
| 380 | + } |
| 381 | + hideSubmenu(id); |
| 382 | +}; |
| 383 | +
|
| 384 | +const closeAndFocusPrev = (id) => { |
| 385 | + if (id === 'products') { |
| 386 | + document.getElementById('logo').focus(); |
| 387 | + } |
| 388 | + hideSubmenu(id); |
| 389 | + const prevMenu = document.querySelector(`#${id}`).closest('li').previousElementSibling?.querySelector('a'); |
| 390 | + if (prevMenu) { |
| 391 | + prevMenu.focus(); |
| 392 | + } |
| 393 | +}; |
| 394 | +
|
250 | 395 | import {Collapse} from 'flowbite';
|
251 | 396 |
|
252 | 397 | const $targetEl = document.getElementById('navbar-top');
|
|
0 commit comments