Skip to content

Commit 7dec8aa

Browse files
committed
Add rule
1 parent baff792 commit 7dec8aa

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// @ts-check
2+
3+
const messages = {
4+
'prefer-action-list-item-onselect': `Use the 'onSelect' event handler instead of 'onClick' for ActionList.Item components, so that it is accessible by keyboard and mouse.`,
5+
}
6+
7+
/** @type {import('@typescript-eslint/utils/ts-eslint').RuleModule<keyof typeof messages>} */
8+
module.exports = {
9+
meta: {
10+
docs: {
11+
description:
12+
'To do something when an `ActionList.Item` is selected, you should use the `onSelect` event handler instead of `onClick`, because it handles both keyboard and mouse events. Otherwise, it will only be accessible by mouse.',
13+
recommended: true,
14+
},
15+
messages,
16+
type: 'problem',
17+
schema: [],
18+
fixable: 'code',
19+
},
20+
defaultOptions: [],
21+
create(context) {
22+
return {
23+
JSXElement(node) {
24+
const isActionListItem =
25+
node.openingElement.name.type === 'JSXMemberExpression' &&
26+
node.openingElement.name.object.type === 'JSXIdentifier' &&
27+
node.openingElement.name.object.name === 'ActionList' &&
28+
node.openingElement.name.property.name === 'Item'
29+
if (!isActionListItem) return
30+
31+
const attributes = node.openingElement.attributes
32+
const onClickAttribute = attributes.find(attr => attr.type === 'JSXAttribute' && attr.name.name === 'onClick')
33+
const onSelectAttribute = attributes.find(attr => attr.type === 'JSXAttribute' && attr.name.name === 'onSelect')
34+
35+
const keyboardHandlers = ['onKeyDown', 'onKeyUp']
36+
const keyboardAttributes = attributes.filter(
37+
attr =>
38+
attr.type === 'JSXAttribute' &&
39+
(typeof attr.name.name === 'string'
40+
? keyboardHandlers.includes(attr.name.name)
41+
: keyboardHandlers.includes(attr.name.name.name)),
42+
)
43+
44+
// If the component has `onSelect`, then it's already using the correct event
45+
if (onSelectAttribute) return
46+
// If there is no `onClick` attribute, then we should also be fine
47+
if (!onClickAttribute) return
48+
// If there is an onClick attribute as well as keyboard handlers, we will assume it is handled correctly
49+
if (onClickAttribute && keyboardAttributes.length > 0) return
50+
51+
context.report({
52+
node: onClickAttribute,
53+
messageId: 'prefer-action-list-item-onselect',
54+
})
55+
},
56+
}
57+
},
58+
}

0 commit comments

Comments
 (0)