Kaynağa Gözat

Add x-trap noinitialfocus modifier (#3977)

* Add x-trap noinitialfocus modifier

Adds a new x-trap modifier: .noinitialfocus to trap focus without
giving focus to the first element in the focus trap

Test included

Relates to discussion #2806

* tweak addition

---------

Co-authored-by: Caleb Porzio <calebporzio@gmail.com>
Richard Carnibella 1 yıl önce
ebeveyn
işleme
ad94a863ee

+ 7 - 0
packages/docs/src/en/plugins/focus.md

@@ -301,6 +301,13 @@ For example:
 </div>
 <!-- END_VERBATIM -->
 
+<a name="noautofocus"></a>
+#### .noautofocus
+
+By default, when `x-trap` traps focous within an element, it focuses the first focussable element within that element. This is a sensible default, however there are times where you may want to disable this behavior and not automatically focus any elements when `x-trap` engages.
+
+By adding `.noautofocus`, Alpine will not automatically focus any elements when trapping focus.
+
 <a name="focus-magic"></a>
 ## $focus
 

+ 6 - 2
packages/focus/src/index.js

@@ -108,9 +108,13 @@ export default function (Alpine) {
                 fallbackFocus: () => el,
             }
 
-            let autofocusEl = el.querySelector('[autofocus]')
+            if (modifiers.includes('noautofocus')) {
+                options.initialFocus = false
+            } else {
+                let autofocusEl = el.querySelector('[autofocus]')
 
-            if (autofocusEl) options.initialFocus = autofocusEl
+                if (autofocusEl) options.initialFocus = autofocusEl
+            }
 
             let trap = createFocusTrap(el, options)
 

+ 28 - 0
tests/cypress/integration/plugins/focus.spec.js

@@ -369,3 +369,31 @@ test('focuses element with autofocus',
         get('#3').should(haveFocus())
     }
 )
+
+test('can disable x-trap autofocus with .noautofocus modifier',
+    [html`
+        <div x-data="{ open: false }">
+            <input type="text" id="1">
+            <button id="2" @click="open = true">open</button>
+            <div>
+                <div x-trap.noautofocus="open">
+                    <input type="text" id="3">
+                    <input autofocus type="text" id="4">
+                    <button @click="open = false" id="5">close</button>
+                </div>
+            </div>
+        </div>
+    `],
+    ({ get }) => {
+        get('#1').click()
+        get('#1').should(haveFocus())
+        get('#2').click()
+        get('#4').should(notHaveFocus())
+        cy.focused().tab()
+        get('#3').should(haveFocus())
+        cy.focused().tab({shift: true})
+        get('#5').should(haveFocus())
+        cy.focused().click()
+        get('#2').should(haveFocus())
+    }
+)