| Server IP : 35.80.110.71 / Your IP : 216.73.216.221 Web Server : Apache/2.4.58 (Ubuntu) System : Linux ip-172-31-21-44 6.17.0-1019-aws #19~24.04.1-Ubuntu SMP Tue Jun 23 18:53:06 UTC 2026 x86_64 User : ubuntu ( 1000) PHP Version : 8.3.31 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/elite-events-storybook/ |
Upload File : |
"use strict";(self.webpackChunkelite_events_nextjs=self.webpackChunkelite_events_nextjs||[]).push([[172],{"./src/hooks/useFocusTrap.stories.tsx":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.r(__webpack_exports__),__webpack_require__.d(__webpack_exports__,{Default:()=>Default,NoAutoFocus:()=>NoAutoFocus,NoRestoreFocus:()=>NoRestoreFocus,__namedExportsOrder:()=>__namedExportsOrder,default:()=>useFocusTrap_stories});var jsx_runtime=__webpack_require__("./node_modules/next/dist/compiled/react/jsx-runtime.js"),react=__webpack_require__("./node_modules/next/dist/compiled/react/index.js");const FOCUSABLE_SELECTORS=["button:not([disabled])","[href]","input:not([disabled])","select:not([disabled])","textarea:not([disabled])",'[tabindex]:not([tabindex="-1"])'].join(", ");function useFocusTrap({isActive,autoFocus=!0,restoreFocus=!0,onEscape}){const containerRef=(0,react.useRef)(null),previousActiveElement=(0,react.useRef)(null),getFocusableElements=(0,react.useCallback)(()=>containerRef.current?Array.from(containerRef.current.querySelectorAll(FOCUSABLE_SELECTORS)):[],[]),focusFirst=(0,react.useCallback)(()=>{const elements=getFocusableElements();elements.length>0&&elements[0].focus()},[getFocusableElements]),focusLast=(0,react.useCallback)(()=>{const elements=getFocusableElements();elements.length>0&&elements[elements.length-1].focus()},[getFocusableElements]);return(0,react.useEffect)(()=>{if(isActive&&containerRef.current&&(restoreFocus&&(previousActiveElement.current=document.activeElement),autoFocus)){const timer=setTimeout(()=>{focusFirst()},0);return()=>clearTimeout(timer)}},[isActive,autoFocus,restoreFocus,focusFirst]),(0,react.useEffect)(()=>{if(!isActive||!containerRef.current)return;const container=containerRef.current,handleKeyDown=event=>{if("Escape"===event.key&&onEscape)return event.preventDefault(),void onEscape();if("Tab"!==event.key)return;const focusableElements=getFocusableElements();if(0===focusableElements.length)return;const firstElement=focusableElements[0],lastElement=focusableElements[focusableElements.length-1],activeElement=document.activeElement;event.shiftKey&&activeElement===firstElement?(event.preventDefault(),lastElement.focus()):event.shiftKey||activeElement!==lastElement||(event.preventDefault(),firstElement.focus())};return container.addEventListener("keydown",handleKeyDown),()=>{container.removeEventListener("keydown",handleKeyDown)}},[isActive,onEscape,getFocusableElements]),(0,react.useEffect)(()=>{!isActive&&restoreFocus&&previousActiveElement.current&&(previousActiveElement.current.focus(),previousActiveElement.current=null)},[isActive,restoreFocus]),{containerRef,getFocusableElements,focusFirst,focusLast}}var Button=__webpack_require__("./src/components/ui/Button/index.tsx");const useFocusTrap_stories={title:"Hooks/useFocusTrap",component:function FocusTrapDemo({autoFocus=!0,restoreFocus=!0}){const[isOpen,setIsOpen]=(0,react.useState)(!1),{containerRef}=useFocusTrap({isActive:isOpen,autoFocus,restoreFocus,onEscape:()=>setIsOpen(!1)});return(0,jsx_runtime.jsxs)("div",{className:"p-8",children:[(0,jsx_runtime.jsx)("div",{className:"mb-4",children:(0,jsx_runtime.jsx)(Button.$,{onClick:()=>setIsOpen(!0),children:"Open Focus Trap"})}),(0,jsx_runtime.jsx)("p",{className:"text-sm text-gray-600 dark:text-gray-400 mb-4",children:"Click the button above, then try pressing Tab. Focus will be trapped within the modal. Press Escape to close."}),isOpen&&(0,jsx_runtime.jsxs)(jsx_runtime.Fragment,{children:[(0,jsx_runtime.jsx)("div",{className:"fixed inset-0 bg-black/50 z-40",onClick:()=>setIsOpen(!1)}),(0,jsx_runtime.jsxs)("div",{ref:containerRef,role:"dialog","aria-modal":"true","aria-labelledby":"dialog-title",className:"fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white dark:bg-gray-800 rounded-lg shadow-xl p-6 z-50 w-96",children:[(0,jsx_runtime.jsx)("h2",{id:"dialog-title",className:"text-xl font-bold mb-4",children:"Focus Trapped Dialog"}),(0,jsx_runtime.jsx)("p",{className:"text-gray-600 dark:text-gray-400 mb-4",children:"Press Tab to cycle through the buttons. Focus stays within this dialog."}),(0,jsx_runtime.jsxs)("div",{className:"space-y-3",children:[(0,jsx_runtime.jsx)("input",{type:"text",placeholder:"First focusable element",className:"w-full px-3 py-2 border rounded dark:bg-gray-700 dark:border-gray-600"}),(0,jsx_runtime.jsx)("input",{type:"email",placeholder:"Email address",className:"w-full px-3 py-2 border rounded dark:bg-gray-700 dark:border-gray-600"}),(0,jsx_runtime.jsxs)("div",{className:"flex justify-end gap-2 pt-4",children:[(0,jsx_runtime.jsx)(Button.$,{variant:"ghost",onClick:()=>setIsOpen(!1),children:"Cancel"}),(0,jsx_runtime.jsx)(Button.$,{onClick:()=>setIsOpen(!1),children:"Save"})]})]})]})]})]})},parameters:{layout:"fullscreen",docs:{description:{component:'\n## useFocusTrap Hook\n\nA React hook for trapping keyboard focus within a container element.\nEssential for modal dialogs, dropdown menus, and other overlay components\nto ensure proper accessibility.\n\n### Features\n- Traps Tab/Shift+Tab focus within container\n- Auto-focuses first element when activated\n- Restores focus to previous element when deactivated\n- Optional Escape key handler\n- Returns utilities for manual focus management\n\n### Accessibility\n- **WCAG 2.4.3 Focus Order**: Maintains logical focus order within the trap\n- **WCAG 2.1.2 No Keyboard Trap**: Focus can be released via Escape or close button\n- **ARIA Authoring Practices**: Follows modal dialog focus management patterns\n\n### Usage\n```tsx\nconst { containerRef } = useFocusTrap<HTMLDivElement>({\n isActive: isModalOpen,\n onEscape: closeModal,\n});\n\nreturn (\n <div ref={containerRef} role="dialog" aria-modal="true">\n {/* Focusable content */}\n </div>\n);\n```\n '}}},tags:["autodocs"]},Default={},NoAutoFocus={args:{autoFocus:!1},parameters:{docs:{description:{story:"When autoFocus is false, the first element is not automatically focused when the trap activates."}}}},NoRestoreFocus={args:{restoreFocus:!1},parameters:{docs:{description:{story:"When restoreFocus is false, focus is not returned to the previously focused element when the trap deactivates."}}}},__namedExportsOrder=["Default","NoAutoFocus","NoRestoreFocus"]}}]);