Просмотр исходного кода

use npm package focus-trap instead of npm package focus-trap-svelte

Sine Jespersen 5 месяцев назад
Родитель
Сommit
305435b4ef
3 измененных файлов с 18 добавлено и 23 удалено
  1. 5 19
      package-lock.json
  2. 1 1
      package.json
  3. 12 3
      src/lib/components/common/Modal.svelte

+ 5 - 19
package-lock.json

@@ -36,6 +36,7 @@
 				"dompurify": "^3.2.5",
 				"eventsource-parser": "^1.1.2",
 				"file-saver": "^2.0.5",
+				"focus-trap": "^7.6.4",
 				"fuse.js": "^7.0.0",
 				"highlight.js": "^11.9.0",
 				"html-entities": "^2.5.3",
@@ -65,7 +66,6 @@
 				"pyodide": "^0.27.3",
 				"socket.io-client": "^4.2.0",
 				"sortablejs": "^1.15.2",
-				"svelte-focus-trap": "^1.2.0",
 				"svelte-sonner": "^0.3.19",
 				"tippy.js": "^6.3.7",
 				"turndown": "^7.2.0",
@@ -6802,9 +6802,10 @@
 			"dev": true
 		},
 		"node_modules/focus-trap": {
-			"version": "7.5.4",
-			"resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.4.tgz",
-			"integrity": "sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==",
+			"version": "7.6.4",
+			"resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.6.4.tgz",
+			"integrity": "sha512-xx560wGBk7seZ6y933idtjJQc1l+ck+pI3sKvhKozdBV1dRZoKhkW5xoCaFv9tQiX5RH1xfSxjuNu6g+lmN/gw==",
+			"license": "MIT",
 			"dependencies": {
 				"tabbable": "^6.2.0"
 			}
@@ -8857,12 +8858,6 @@
 				"pathe": "^2.0.1"
 			}
 		},
-		"node_modules/mousetrap": {
-			"version": "1.6.5",
-			"resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.5.tgz",
-			"integrity": "sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==",
-			"license": "Apache-2.0 WITH LLVM-exception"
-		},
 		"node_modules/mri": {
 			"version": "1.2.0",
 			"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
@@ -11417,15 +11412,6 @@
 				}
 			}
 		},
-		"node_modules/svelte-focus-trap": {
-			"version": "1.2.0",
-			"resolved": "https://registry.npmjs.org/svelte-focus-trap/-/svelte-focus-trap-1.2.0.tgz",
-			"integrity": "sha512-/hIUHgKcFlewsQreq8v7DYNBkQe7rR0c94PNBOCsmeUwoIYAy6iXJ1pH0k3rWpjwZHKtUxeXbX1iRFlFhipbeg==",
-			"license": "MIT",
-			"dependencies": {
-				"mousetrap": "^1.6.5"
-			}
-		},
 		"node_modules/svelte-hmr": {
 			"version": "0.16.0",
 			"resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.16.0.tgz",

+ 1 - 1
package.json

@@ -79,6 +79,7 @@
 		"dompurify": "^3.2.5",
 		"eventsource-parser": "^1.1.2",
 		"file-saver": "^2.0.5",
+		"focus-trap": "^7.6.4",
 		"fuse.js": "^7.0.0",
 		"highlight.js": "^11.9.0",
 		"html-entities": "^2.5.3",
@@ -108,7 +109,6 @@
 		"pyodide": "^0.27.3",
 		"socket.io-client": "^4.2.0",
 		"sortablejs": "^1.15.2",
-		"svelte-focus-trap": "^1.2.0",
 		"svelte-sonner": "^0.3.19",
 		"tippy.js": "^6.3.7",
 		"turndown": "^7.2.0",

+ 12 - 3
src/lib/components/common/Modal.svelte

@@ -3,7 +3,7 @@
 	import { fade } from 'svelte/transition';
 
 	import { flyAndScale } from '$lib/utils/transitions';
-	import { focusTrap } from 'svelte-focus-trap'
+	import * as FocusTrap from 'focus-trap'
 	export let show = true;
 	export let size = 'md';
 	export let containerClassName = 'p-3';
@@ -11,6 +11,10 @@
 
 	let modalElement = null;
 	let mounted = false;
+	// Create focus trap to trap user tabs inside modal
+	// https://www.w3.org/WAI/WCAG21/Understanding/focus-order.html
+	// https://www.w3.org/WAI/WCAG21/Understanding/keyboard.html
+	let focusTrap: FocusTrap.FocusTrap | null = null;
 
 	const sizeToWidth = (size) => {
 		if (size === 'full') {
@@ -42,12 +46,15 @@
 	onMount(() => {
 		mounted = true;
 	});
-
+	
 	$: if (show && modalElement) {
 		document.body.appendChild(modalElement);
+		focusTrap = FocusTrap.createFocusTrap(modalElement);
+		focusTrap.activate();
 		window.addEventListener('keydown', handleKeyDown);
 		document.body.style.overflow = 'hidden';
 	} else if (modalElement) {
+		focusTrap.deactivate();
 		window.removeEventListener('keydown', handleKeyDown);
 		document.body.removeChild(modalElement);
 		document.body.style.overflow = 'unset';
@@ -55,6 +62,9 @@
 
 	onDestroy(() => {
 		show = false;
+		if (focusTrap) {
+			focusTrap.deactivate();
+		}
 		if (modalElement) {
 			document.body.removeChild(modalElement);
 		}
@@ -66,7 +76,6 @@
 	<!-- svelte-ignore a11y-no-static-element-interactions -->
 	<div
 		bind:this={modalElement}
-		use:focusTrap
 		aria-modal="true"
 		role="dialog"
 		class="modal fixed top-0 right-0 left-0 bottom-0 bg-black/60 w-full h-screen max-h-[100dvh] {containerClassName} flex justify-center z-9999 overflow-y-auto overscroll-contain"