@@ -45,19 +45,23 @@ function isMenuItemNode(node) {
4545 return getTextAttr ( node , 'role' ) === 'menuitem' ;
4646}
4747
48- function isSummaryFirstChildOfDetails ( summaryNode , parentEntry ) {
49- if ( summaryNode . tag !== 'summary' || parentEntry . tag !== 'details' ) {
48+ function isAllowedDetailsChild ( childNode , parentEntry ) {
49+ if ( parentEntry . tag !== 'details' ) {
5050 return false ;
5151 }
52- const parentNode = parentEntry . node ;
53- const children = parentNode . children || [ ] ;
52+ // Non-<summary> children are flow content in the disclosed panel — allowed.
53+ // <summary> is only allowed as the first non-whitespace child of <details>.
54+ if ( childNode . tag !== 'summary' ) {
55+ return true ;
56+ }
57+ const children = parentEntry . node . children || [ ] ;
5458 const firstNonWhitespace = children . find ( ( child ) => {
5559 if ( child . type === 'GlimmerTextNode' ) {
5660 return child . chars . trim ( ) . length > 0 ;
5761 }
5862 return true ;
5963 } ) ;
60- return firstNonWhitespace === summaryNode ;
64+ return firstNonWhitespace === childNode ;
6165}
6266
6367/** @type {import('eslint').Rule.RuleModule } */
@@ -208,8 +212,8 @@ module.exports = {
208212 } ) ;
209213 }
210214 parentEntry . interactiveChildCount ++ ;
211- } else if ( isSummaryFirstChildOfDetails ( node , parentEntry ) ) {
212- // <summary> as first non-whitespace child of <details> is allowed
215+ } else if ( isAllowedDetailsChild ( node , parentEntry ) ) {
216+ // flow content in the disclosed panel, or <summary> as first child
213217 } else if ( isMenuItemNode ( parentEntry . node ) && isMenuItemNode ( node ) ) {
214218 // Nested menuitem nodes are valid (menu/sub-menu pattern)
215219 } else {
0 commit comments