Skip to content

Commit

Permalink
[fix] Refine implicit role of select to include combobox scenarios
Browse files Browse the repository at this point in the history
Encode implicit roles for `select` elements based on roles defined in https://www.w3.org/TR/html-aria/#el-select

- `select` (with a multiple attribute or a size attribute having value greater than 1) will have the implicit role 'listbox'
- `select` (with NO multiple attribute and NO size attribute having value greater than 1) will have the implicit role 'combobox'

Fixes jsx-eslint#949
  • Loading branch information
lb- committed Oct 23, 2024
1 parent e5dda96 commit c1e47c1
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 3 deletions.
7 changes: 7 additions & 0 deletions __tests__/src/rules/no-redundant-roles-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,19 @@ const alwaysValid = [
{ code: '<MyComponent role="button" />' },
{ code: '<button role={`${foo}button`} />' },
{ code: '<Button role={`${foo}button`} />', settings: componentsSettings },
{ code: '<select role="menu"><option>1</option><option>2</option></select>' },
];

const neverValid = [
{ code: '<button role="button" />', errors: [expectedError('button', 'button')] },
{ code: '<body role="DOCUMENT" />', errors: [expectedError('body', 'document')] },
{ code: '<Button role="button" />', settings: componentsSettings, errors: [expectedError('button', 'button')] },
{ code: '<select role="combobox" size />', errors: [expectedError('select', 'combobox')] },
{ code: '<select role="combobox" size={1} />', errors: [expectedError('select', 'combobox')] },
{ code: '<select role="combobox"><option>1</option><option>2</option></select>', errors: [expectedError('select', 'combobox')] },
{ code: '<select role="listbox" size="3" />', errors: [expectedError('select', 'listbox')] },
{ code: '<select role="listbox" size={2} />', errors: [expectedError('select', 'listbox')] },
{ code: '<select role="listbox" multiple><option>1</option><option>2</option></select>', errors: [expectedError('select', 'listbox')] },
];

ruleTester.run(`${ruleName}:recommended`, rule, {
Expand Down
17 changes: 14 additions & 3 deletions src/util/implicitRoles/select.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import { getProp, getLiteralPropValue } from 'jsx-ast-utils';

/**
* Returns the implicit role for a select tag.
* Returns the implicit role for a select tag depending on attributes.
*
* @see https://www.w3.org/TR/html-aria/#el-select
*/
export default function getImplicitRoleForSelect() {
return 'listbox';
export default function getImplicitRoleForSelect(attributes) {
const multiple = getProp(attributes, 'multiple');
if (multiple) return 'listbox';

const size = getProp(attributes, 'size');
const sizeValue = size && getLiteralPropValue(size);
if (sizeValue && (Number(sizeValue) > 1)) return 'listbox';

return 'combobox';
}

0 comments on commit c1e47c1

Please sign in to comment.