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

LPS-201300 Fixing Accessibility Issue at Clay Panel Component #5716

Merged
merged 1 commit into from
Nov 29, 2023

Conversation

AkramYoussoufi
Copy link
Contributor

@AkramYoussoufi AkramYoussoufi force-pushed the LPS-201300 branch 3 times, most recently from cea4627 to 76b7672 Compare November 10, 2023 11:30
@ethib137
Copy link
Member

Hi @AkramYoussoufi , did you try using this component after your changes with your keyboard and a screen reader? You'll notice not much info is provided when interacting with a panel. We need these roles to make it work properly with accessible technologies.

@AkramYoussoufi
Copy link
Contributor Author

AkramYoussoufi commented Nov 10, 2023

Hi @ethib137, I have uploaded a video in the comment section in the Ticket to check.

@ethib137
Copy link
Member

Hey @AkramYoussoufi , this change still won't work. It breaks the proper HTML semantics. Mozilla explains here:

Elements with the role tab must either be a child of an element with the tablist role, or have their id as part of the aria-owns property of a tablist.

Since you have removed the tablist role entirely, this breaks those requirements.

@AkramYoussoufi AkramYoussoufi force-pushed the LPS-201300 branch 3 times, most recently from f45dfc4 to 59f8e81 Compare November 14, 2023 10:03
@AkramYoussoufi
Copy link
Contributor Author

AkramYoussoufi commented Nov 14, 2023

@ethib137 in this changes, I have fixed the conflict happens between ClayGroupPanel and ClayPanelComponent

Because the GroupPanel Component has its own role="tablist"


const ClayPanelGroup = ({
	children,
	className,
	fluid,
	fluidFirst,
	fluidLast,
	flush,
	small,
	...otherProps
}: IProps) => {
	return (
		<div
			{...otherProps}
			aria-orientation="vertical"
			className={classNames('panel-group', className, {
				'panel-group-fluid': fluid,
				'panel-group-fluid-first': fluidFirst,
				'panel-group-fluid-last': fluidLast,
				'panel-group-flush': flush,
				'panel-group-sm': small,
			})}
			role="tablist"
		>
			{children}
		</div>
	);
};

and on the ClayPanelComponent also has the tablist role

this cause issue when using ClayPanelGroup and ClayPanel Component together ex:

	<ClayPanel.Group>
		{['One', 'Two', 'Three'].map((item) => (
			<ClayPanel
				collapsable
				displayTitle={item}
				key={item}
				showCollapseIcon
			>
				<ClayPanel.Body>
					{`Here is some content inside for number ${item}`}
				</ClayPanel.Body>
			</ClayPanel>
		))}
	</ClayPanel.Group>

in this scenario, the ClayPanelGroup will look for an element with tab and tabpanel and will not find them because the ClayPanel assigns to it the tab and tabpanel as its own element causing the ClayPanel.Group triggering the issue of missing elements when scanning with devTools.

I have added a checker which check if the GroupPanel is used as parent if yes in this case the ClayPanel will not use role=tabpanel and leave it to the ClayPanelGroup to handle the assignment.

@AkramYoussoufi AkramYoussoufi force-pushed the LPS-201300 branch 4 times, most recently from 9448efd to 9b5b89e Compare November 14, 2023 10:37
@AkramYoussoufi
Copy link
Contributor Author

AkramYoussoufi commented Nov 14, 2023

one problem present now is that ClayPanel Component uses the ClayPanel.Body as its own child this caused problems since the ClayPanel.Body has and must have the tabpanel role.

based on mozilla doc you gave me and devTools scanner
image
the tabpanel should not be a child to the tablist but rather it needs to be a sibling!

and the ClayPanel Component is built to receive the ClayPanel.Body as its own child! based on the code source and this is the normal implementation :

			<ClayPanel
				collapsable
				displayTitle={item}
				key={item}
				showCollapseIcon
			>
				<ClayPanel.Body>
					{`Here is some content inside for number ${item}`}
				</ClayPanel.Body>
			</ClayPanel>

we can fix this technically by making the


				<ClayPanel.Body>
					{`Here is some content inside for number ${item}`}
				</ClayPanel.Body>

outside the ClayPanel ex:

			<ClayPanel
				collapsable
				displayTitle={item}
				key={item}
				showCollapseIcon
			/>
			<ClayPanel.Body>
				{`Here is some content inside for number ${item}`}
			</ClayPanel.Body>

like this ClayPanel will act as the tab while the ClayPanel.Body act as the tabpanel but still we will need to assign ClayPanel.Group as the parent to the ClayPanel with role="tablist" to be in the correct structure

	<ClayPanel.Group>
			<ClayPanel
				collapsable
				displayTitle={item}
				key={item}
				showCollapseIcon
			>
			</ClayPanel>
	</ClayPanel.Group>
	<ClayPanel.Body>
		{`Here is some content inside for number ${item}`}
	</ClayPanel.Body>

like this we will have

-tablist
  --tab
-tabpanel 

as the right structure and ClayGroup will became a must use case for the ClayPanel

@AkramYoussoufi
Copy link
Contributor Author

Hello @ethib137, disclosure pattern is implemented

Copy link
Member

@ethib137 ethib137 left a comment

Choose a reason for hiding this comment

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

Thanks @AkramYoussoufi . Couple things to change... Also the deploy preview is braking, so it would be good to look into why.

@@ -146,9 +146,9 @@ function ClayPanel({
show: internalExpanded,
}
)}
data-disclosure
Copy link
Member

Choose a reason for hiding this comment

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

What is the purpose of adding this data attribute?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is a mark defining the pattern used in this element

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I removed it

@@ -135,6 +134,7 @@ function ClayPanel({
{collapsable && (
<>
<ClayButton
aria-controls="panel-body"
Copy link
Member

Choose a reason for hiding this comment

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

The value of aria-controls needs to be the id of the element it controls.

https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed!

@AkramYoussoufi AkramYoussoufi force-pushed the LPS-201300 branch 4 times, most recently from 5d98985 to 0b3ba3c Compare November 27, 2023 11:26
@AkramYoussoufi
Copy link
Contributor Author

@ethib137 required pattern is implemented I added a logic that will look for the number of panels within the parent element and give each panel element its needed index within a group of panels.

@AkramYoussoufi
Copy link
Contributor Author

@ethib137 I don't understand why the CI return failed on the test because the test in my local passed successfully:

$ npm run test

> @clayui/[email protected] test
> jest --config ../../jest.config.js --updateSnapshot

ts-jest[versions] (WARN) Version 27.5.1 of jest installed has not been tested with ts-jest. If you're experiencing issues, consider using a supported version (>=28.0.0 <29.0.0-0). Please do not report issues in ts-jest if you are using unsupported versions.
 PASS  src/__tests__/index.tsx (6.488 s)
  ClayPanel
    ✓ renders (31 ms)
    ✓ renders with different displayType (7 ms)
    ✓ renders with multiple panels (20 ms)
    ✓ renders with multiple small panels (9 ms)
    ✓ renders with custom displayTitle (5 ms)
    ✓ renders without displayTitle (4 ms)
  ClayPanel Interactions
    ✓ clicking the title should expand and close the content (21 ms)

@@ -135,6 +151,7 @@ function ClayPanel({
{collapsable && (
<>
<ClayButton
aria-controls={`panel-index-${indexOfElement}`}
Copy link
Member

Choose a reason for hiding this comment

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

Hey @AkramYoussoufi can you look at other instances of how we generate an ID for aria-controls and copy that pattern?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure thing

@AkramYoussoufi
Copy link
Contributor Author

@ethib137 Done!

@@ -201,7 +204,6 @@ function ClayPanel({
onExiting={(element) => {
element.style.height = '';
}}
role="tabpanel"
Copy link
Member

Choose a reason for hiding this comment

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

I was talking to Marcos about this and one of the things we can follow here is to use the w3c accessibility recommendation for accordion which is similar to panel https://www.w3.org/WAI/ARIA/apg/patterns/accordion/examples/accordion/, we can add role="region" here instead of tabpanel. The other implementations part is ok too.

@@ -18,7 +18,7 @@
"build": "cross-env NODE_ENV=production babel src --root-mode upward --out-dir lib --extensions .ts,.tsx",
"buildTypes": "cross-env NODE_ENV=production tsc --project ./tsconfig.declarations.json",
"prepublishOnly": "yarn build && yarn buildTypes",
"test": "jest --config ../../jest.config.js"
"test": "jest --config ../../jest.config.js --updateSnapshot"
Copy link
Member

Choose a reason for hiding this comment

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

You can remove updateSnapshot here, we don't want this command by default because it will make the snapshot unusable we should only use it when we intend to update the markup. If you maintain this, we can update in a snapshot in cases where the markup change is a bug.

@AkramYoussoufi
Copy link
Contributor Author

AkramYoussoufi commented Nov 28, 2023

@matuzalemsteles @ethib137 all the changes have been implemented

I don't understand what causes netlify to fail but my jest and build is working perfectly fine in my local.

Copy link
Member

@matuzalemsteles matuzalemsteles left a comment

Choose a reason for hiding this comment

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

LGTM! These storybook and website errors don't make any sense, I'll go ahead and see if the builds still fail on master.

@matuzalemsteles matuzalemsteles merged commit 5eaf690 into liferay:master Nov 29, 2023
2 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants