File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -84,13 +84,19 @@ function getRole(node) {
8484 if ( explicit === null ) {
8585 return null ;
8686 }
87- const first = explicit . trim ( ) . split ( / \s + / ) [ 0 ] ?. toLowerCase ( ) ;
88- if ( first && roles . has ( first ) ) {
89- return first ;
87+ // Walk the whitespace-separated token list for the first RECOGNISED
88+ // role, matching WAI-ARIA §4.1 role-fallback semantics — UAs skip
89+ // unknown tokens and pick the first they implement. `role="xxyxyz
90+ // button"` resolves to `button`; later tokens are graceful-degradation
91+ // fallbacks. Unknown-only lists fall through to the implicit role.
92+ const tokens = explicit . trim ( ) . toLowerCase ( ) . split ( / \s + / u) ;
93+ for ( const token of tokens ) {
94+ if ( token && roles . has ( token ) ) {
95+ return token ;
96+ }
9097 }
91- // `role` present with an unknown token (e.g. `role="bogus"`) — per ARIA
92- // the invalid value is ignored and the implicit role applies. Fall
93- // through to the implicit-role lookup.
98+ // `role` present but no recognised token (e.g. `role="bogus"`) — per
99+ // ARIA, invalid values are ignored and the implicit role applies.
94100 }
95101 return getImplicitRole ( node ) ;
96102}
Original file line number Diff line number Diff line change @@ -48,6 +48,10 @@ const validHbs = [
4848 // false-flag against the element's implicit role.
4949 '<div role={{this.role}} aria-label="x">x</div>' ,
5050 '<span role={{this.role}} aria-labelledby="t">x</span>' ,
51+ // Role-fallback: UAs walk unknown leading tokens to the first recognised
52+ // role per WAI-ARIA §4.1. `role="xxyxyz button"` resolves to `button`,
53+ // which accepts aria-label — should not flag.
54+ '<div role="xxyxyz button" aria-label="Custom">x</div>' ,
5155] ;
5256
5357const invalidHbs = [
You can’t perform that action at this time.
0 commit comments