diff --git a/packages/vue/src/composables/useFocusGuard/index.test.ts b/packages/vue/src/composables/useFocusGuard/index.test.ts
new file mode 100644
index 0000000..f646716
--- /dev/null
+++ b/packages/vue/src/composables/useFocusGuard/index.test.ts
@@ -0,0 +1,69 @@
+import { describe, it, beforeEach, afterEach, expect } from 'vitest';
+import { mount } from '@vue/test-utils';
+import { defineComponent, nextTick } from 'vue';
+import { useFocusGuard } from '.';
+
+const setupFocusGuard = (namespace?: string) => {
+ return mount(
+ defineComponent({
+ setup() {
+ useFocusGuard(namespace);
+ },
+ template: '
',
+ })
+ );
+};
+
+const getFocusGuards = (namespace: string) =>
+ document.querySelectorAll(`[data-${namespace}]`);
+
+describe('useFocusGuard', () => {
+ let component: ReturnType;
+ const namespace = 'test-guard';
+
+ beforeEach(() => {
+ document.body.innerHTML = '';
+ });
+
+ afterEach(() => {
+ component.unmount();
+ });
+
+ it('create focus guards when mounted', async () => {
+ component = setupFocusGuard(namespace);
+
+ const guards = getFocusGuards(namespace);
+ expect(guards.length).toBe(2);
+
+ guards.forEach((guard) => {
+ expect(guard.getAttribute('tabindex')).toBe('0');
+ expect(guard.getAttribute('style')).toContain('opacity: 0');
+ });
+ });
+
+ it('remove focus guards when unmounted', () => {
+ component = setupFocusGuard(namespace);
+
+ component.unmount();
+
+ expect(getFocusGuards(namespace).length).toBe(0);
+ });
+
+ it('correctly manage multiple instances with the same namespace', () => {
+ const wrapper1 = setupFocusGuard(namespace);
+ const wrapper2 = setupFocusGuard(namespace);
+
+ // Guards should not be duplicated
+ expect(getFocusGuards(namespace).length).toBe(2);
+
+ wrapper1.unmount();
+
+ // Second instance still keeps the guards
+ expect(getFocusGuards(namespace).length).toBe(2);
+
+ wrapper2.unmount();
+
+ // No guards left after all instances are unmounted
+ expect(getFocusGuards(namespace).length).toBe(0);
+ });
+});
diff --git a/packages/vue/src/composables/useFocusGuard/index.ts b/packages/vue/src/composables/useFocusGuard/index.ts
new file mode 100644
index 0000000..a547522
--- /dev/null
+++ b/packages/vue/src/composables/useFocusGuard/index.ts
@@ -0,0 +1,40 @@
+import { focusGuard } from '@robonen/platform/browsers';
+import { onMounted, onUnmounted } from 'vue';
+
+// Global counter to drop the focus guards when the last instance is unmounted
+let counter = 0;
+
+/**
+ * @name useFocusGuard
+ * @category Utilities
+ * @description Adds a pair of focus guards at the boundaries of the DOM tree to ensure consistent focus behavior
+ *
+ * @param {string} [namespace] - A namespace to group the focus guards
+ * @returns {void}
+ *
+ * @example
+ * useFocusGuard();
+ *
+ * @example
+ * useFocusGuard('my-namespace');
+ *
+ * @since 0.0.2
+ */
+export function useFocusGuard(namespace?: string) {
+ const manager = focusGuard(namespace);
+
+ const createGuard = () => {
+ manager.createGuard();
+ counter++;
+ };
+
+ const removeGuard = () => {
+ if (counter <= 1)
+ manager.removeGuard();
+
+ counter = Math.max(0, counter - 1);
+ };
+
+ onMounted(createGuard);
+ onUnmounted(removeGuard);
+}
diff --git a/packages/vue/src/types/window.ts b/packages/vue/src/types/window.ts
index afa5061..bfd076b 100644
--- a/packages/vue/src/types/window.ts
+++ b/packages/vue/src/types/window.ts
@@ -1,3 +1,3 @@
-import { isClient } from '@robonen/platform';
+import { isClient } from '@robonen/platform/multi';
export const defaultWindow = /* #__PURE__ */ isClient ? window : undefined
\ No newline at end of file