Bläddra i källkod

Use the hidden attribute & `display:none` to hide x-collapse content from the accessibility tree (#2353)

* Use the hidden attribute to hide x-collapse content accessibly

* Remove unused Cypress method that was being imported

* Fix issue with missing in transition

* Add display:none rules to prevent potential CSS specificity issues with the hidden attribute

* Undo unintentional formatting change

* Do not remove the initial style.display set by x-show

* Fix double closing of link element in x-collapse test

Co-authored-by: Chris Rowe <mail@chrisrowe.net>

Co-authored-by: Chris Rowe <mail@chrisrowe.net>
Phil Wolstenholme 3 år sedan
förälder
incheckning
a1900ad040
2 ändrade filer med 23 tillägg och 7 borttagningar
  1. 16 4
      packages/collapse/src/index.js
  2. 7 3
      tests/cypress/integration/plugins/collapse.spec.js

+ 16 - 4
packages/collapse/src/index.js

@@ -4,7 +4,12 @@ export default function (Alpine) {
         let floor = 0
 
         if (! el._x_isShown) el.style.height = `${floor}px`
-        if (! el._x_isShown) el.style.removeProperty('display')
+        // We use the hidden attribute for the benefit of Tailwind
+        // users as the .space utility will ignore [hidden] elements.
+        // We also use display:none as the hidden attribute has very
+        // low CSS specificity and could be accidentally overriden
+        // by a user.
+        if (! el._x_isShown) el.hidden = true
         if (! el._x_isShown) el.style.overflow = 'hidden'
 
         // Override the setStyles function with one that won't
@@ -24,9 +29,12 @@ export default function (Alpine) {
 
         el._x_transition = {
             in(before = () => {}, after = () => {}) {
+                el.hidden = false;
+
                 let current = el.getBoundingClientRect().height
 
                 Alpine.setStyles(el, {
+                    display: null,
                     height: 'auto',
                 })
 
@@ -57,9 +65,13 @@ export default function (Alpine) {
 
                     // check if element is fully collapsed
                     if (el.style.height == `${floor}px`) {
-                        Alpine.nextTick(() => Alpine.setStyles(el, {
-                            overflow: 'hidden'
-                        }))
+                        Alpine.nextTick(() => {
+                            Alpine.setStyles(el, {
+                                display: 'none',
+                                overflow: 'hidden'
+                            })
+                            el.hidden = true;
+                        })
                     }
                 })
             },

+ 7 - 3
tests/cypress/integration/plugins/collapse.spec.js

@@ -1,19 +1,23 @@
-import { haveAttribute, haveComputedStyle, html, test } from '../../utils'
+import { haveAttribute, haveComputedStyle, html, notHaveAttribute, test } from '../../utils'
 
 test('can collapse and expand element',
     [html`
         <div x-data="{ expanded: false }">
             <button @click="expanded = ! expanded">toggle</button>
-            <h1 x-show="expanded" x-collapse>contents</h1>
+            <h1 x-show="expanded" x-collapse>contents <a href="#">focusable content</a></h1>
         </div>
     `],
     ({ get }, reload) => {
         get('h1').should(haveComputedStyle('height', '0px'))
-        get('h1').should(haveAttribute('style', 'height: 0px; overflow: hidden;'))
+        get('h1').should(haveAttribute('style', 'display: none; height: 0px; overflow: hidden;'))
+        get('h1').should(haveAttribute('hidden', 'hidden'))
         get('button').click()
         get('h1').should(haveAttribute('style', 'height: auto;'))
+        get('h1').should(notHaveAttribute('hidden'))
         get('button').click()
         get('h1').should(haveComputedStyle('height', '0px'))
+        get('h1').should(haveAttribute('style', 'height: 0px; display: none; overflow: hidden;'))
+        get('h1').should(haveAttribute('hidden', 'hidden'))
     },
 )