Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A11y: Introduce ClickableElement #7977

Merged
merged 6 commits into from
Mar 19, 2024
Merged

A11y: Introduce ClickableElement #7977

merged 6 commits into from
Mar 19, 2024

Conversation

fregante
Copy link
Collaborator

@fregante fregante commented Mar 19, 2024

What does this PR do?

This component and lint rule essentially replaces most instances of:

This also documents the usage of clickable div elements and ensures consistent/safe usage.

Checklist

Copy link

codecov bot commented Mar 19, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 73.06%. Comparing base (0c94f1d) to head (9fc198d).
Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7977      +/-   ##
==========================================
+ Coverage   73.05%   73.06%   +0.01%     
==========================================
  Files        1299     1300       +1     
  Lines       40372    40376       +4     
  Branches     7506     7505       -1     
==========================================
+ Hits        29492    29500       +8     
+ Misses      10880    10876       -4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@fregante fregante changed the title A11y: Introduce ClickableEleemnt A11y: Introduce ClickableElement Mar 19, 2024
> = ({ children, ...props }) => (
<div
{...props}
tabIndex={0}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why specify the tabIndex specifically as 0? Won't this mess up the tab order on the page?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would set tabIndex={0} before spreading props, so we can choose to override it otherwise.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, 0 value basically will let the dom auto-order these focusable elements.
https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea in theory, but in practice we should never set tabIndex > 0 https://webaim.org/techniques/keyboard/tabindex#tabindex

* - https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/mouse-events-have-key-events.md
*
*/
const ClickableElement: React.FC<
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also probably include some default styling for cursor: pointer

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be best to address that globally, for all role=button, via CSS. I can open a followup PR that takes care of all existing definitions for that

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good to me

props.onClick(event);
}
}}
// TODO: also handle onMouseOver -> onFocus
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What custom logic were you thinking for these events?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's part of one of the a11y rules linked above. However in reality we should just avoid such events and use CSS instead

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha. It wasn't clear from this TODO comment what it was referring to.

It seems like this could be addressed with some TS discriminated unions but I'm also not sure we even want to always enforce this rule. For example, a popular pattern for form inputs is to autosave onBlur, but not onMouseLeave.

const handleClick = jest.fn();
render(<ClickableElement onClick={handleClick} />);
const clickableElement = screen.getByRole("button");
fireEvent.keyPress(clickableElement, {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: why not use userEvent.keyboard?

Copy link
Collaborator Author

@fregante fregante Mar 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was copiloted. I can change it if you prefer

@fregante fregante added the backlog PRs with unresolved "future work" label Mar 19, 2024
@fungairino fungairino merged commit 0aa1b7d into main Mar 19, 2024
18 checks passed
@fungairino fungairino deleted the F/a11y/clickable-element branch March 19, 2024 19:02
@twschiller twschiller added this to the 1.8.11 milestone Mar 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a11y backlog PRs with unresolved "future work" low priority
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants