🚧 Work in progress 🚧
- Trying to build accessible dropdown menus / navigation bars with Svelte(Kit) and Floating UI.
- Floating UI takes care of positioning dropdowns / popovers. It only detects resizing / scroll actions and positions dropdowns / popovers accordingly (https://blog.logrocket.com/popper-vs-floating-ui/)
- Based on https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/.
- Experimental, do not use this in production without serious a11y testing!
Live demo: https://svelte-floating-ui-a11y-menu.vercel.app/
npm install
npm run dev -- --open
-
npm run storybook
-
(not compatible yet) https://storybook.js.org/addons/@storybook/addon-svelte-csf
-
Add focus styles for mobile menu
-
Improve focus styles
-
Add escape key for mobile dialog overlay
-
Add current active link and mark it with
aria-current=
-
Add focus trap for mobile menu overlay (https://www.npmjs.com/package/svelte-focus-trap ?)
-
Use all keyboard events (arrow up, down) of https://w3c.github.io/aria-practices/examples/disclosure/disclosure-navigation.html
-
Integrate Example Disclosure Navigation Menu with Top-Level Links
-
Check if Floating UI autoUpdater was written reliable and dumps all old listeners / switch to Svelte solution for resize / scrolling detection?
-
Bonus: Handle all resize cases and hide menus if menus switch between mobile & desktop?
- e.g. mobile overlay open -> resize window to desktop
-
Read https://adrianroselli.com/2019/06/link-disclosure-widget-navigation.html
-
Fix contrast errors
-
Test with screenreaders!
-
Get feedback by a11y experts!
I did not use {#if activeMenu == 'news'}
around <ul>
-submenus, because this removes submenus temporarily completely from DOM. I wasn't sure if this was okay with aria-controls= references (https://stackoverflow.com/a/73391142). Drawback is, that you can't use Svelte animations like in:fly={{ y: -10 }}
on these submenus.
Instead I used a .hide
-class (provided by Foxeye.Rinx), this does not remove elements from DOM. See feat: svelte-display directive #6336 #7932 for more details.
- Why JS positioning for dropdowns? https://blog.logrocket.com/popper-vs-floating-ui/
- Cancel in
touchstart
events to not trigger click events as well https://web.dev/mobile-touchandmouse/ - Related: picocss/pico#330 (thx to @matuzo!)
- https://w3c.github.io/aria-practices/examples/menubar/menubar-navigation.html
- Maybe relevant in future: jguze/svelte-easy-popover#4
- For Vanilla JS: https://github.com/NickDJM/accessible-menu
- https://bholmes.dev/blog/building-a-sexy-mobile-ready-navbar-in-any-web-framework/
- https://bholmes.dev/blog/accessible-show-hide-animations/
- Practical example (not mine): https://www.wien.gv.at/spezial/cd-manual/
npm create svelte@latest .
npm install @floating-ui/dom
npm i @picocss/pico sass svelte-preprocess