Skip to content

Commit

Permalink
fix: eslint a11y rules (#1079)
Browse files Browse the repository at this point in the history
* fix: eslint a11y rules

* fix: tests
  • Loading branch information
PahaN47 authored Nov 15, 2024
1 parent ce49fb6 commit e5378e9
Show file tree
Hide file tree
Showing 13 changed files with 93 additions and 54 deletions.
4 changes: 4 additions & 0 deletions src/blocks/Questions/QuestionBlockItem/QuestionBlockItem.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@ $block: '.#{$ns}QuestionsBlockItem';
}

&__title {
@include reset-button-style();
@include heading4();
@include focusable();

position: relative;
display: block;
width: 100%;
padding-right: 24px;
text-align: start;
cursor: pointer;
border-radius: var(--g-focus-border-radius);

Expand Down
8 changes: 2 additions & 6 deletions src/blocks/Questions/QuestionBlockItem/QuestionBlockItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,10 @@ export const QuestionBlockItem = ({
itemType={FaqMicrodataValues.QuestionType}
role={'listitem'}
>
<h3
<button
className={b('title')}
onClick={onClick}
aria-expanded={isOpened}
// TODO fix in https://github.com/gravity-ui/page-constructor/issues/966
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-to-interactive-role
role={'button'}
tabIndex={0}
onKeyDown={onKeyDown}
>
<HTML itemProp={FaqMicrodataValues.QuestionNameProp}>{itemTitle}</HTML>
Expand All @@ -48,7 +44,7 @@ export const QuestionBlockItem = ({
iconType="navigation"
className={b('arrow')}
/>
</h3>
</button>
<Foldable isOpened={isOpened}>
<div
className={b('text')}
Expand Down
7 changes: 3 additions & 4 deletions src/components/ImageBase/ImageBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,17 @@ export interface ImageBaseProps extends Partial<ImageObjectProps> {
onError?: () => void;
}

export const ImageBase = ({fetchPriority, ...props}: ImageBaseProps) => {
export const ImageBase = ({fetchPriority, alt, ...props}: ImageBaseProps) => {
const {Image} = React.useContext(ImageContext);

return Image ? (
<Image fetchPriority={fetchPriority} {...props} />
<Image fetchPriority={fetchPriority} alt={alt} {...props} />
) : (
// There is an issue with fetchpriority attr in img in React.
// It is still not supported. However it's nice to have ability to manage
// this prop is good to have to improve Core Web Vitals.
// So, here is a workaround to assign the attr.
// eslint-disable-next-line jsx-a11y/alt-text
<img {...{fetchpriority: fetchPriority}} {...props} />
<img {...{fetchpriority: fetchPriority}} alt={alt} {...props} />
);
};

Expand Down
18 changes: 12 additions & 6 deletions src/components/OutsideClick/OutsideClick.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
// TODO fix in https://github.com/gravity-ui/page-constructor/issues/965

//TODO move into cloud components?
import React, {PropsWithChildren, createRef} from 'react';

import noop from 'lodash/noop';

export interface OutsideClickProps {
onOutsideClick: () => void;
className?: string;
Expand All @@ -23,9 +21,17 @@ export default class OutsideClick extends React.Component<PropsWithChildren<Outs
}

render() {
const {className, onClick, children} = this.props;
const {children, className, onClick} = this.props;

return (
<div className={className} ref={this.ref} onClick={onClick}>
<div
className={className}
ref={this.ref}
onClick={onClick}
onKeyDown={noop}
role={onClick ? 'button' : 'group'}
tabIndex={onClick ? 0 : -1}
>
{children}
</div>
);
Expand Down
21 changes: 16 additions & 5 deletions src/components/ReactPlayer/ReactPlayer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
// TODO fix in https://github.com/gravity-ui/page-constructor/issues/965

import React, {
Fragment,
useCallback,
Expand Down Expand Up @@ -110,6 +106,7 @@ export const ReactPlayerBlock = React.forwardRef<ReactPlayerBlockHandler, ReactP
const {playingVideoRef, setProps} = useContext(VideoContext);

const ref = useRef<HTMLDivElement>(null);
const buttonRef = useRef<HTMLButtonElement>(null);

const [playerRef, setPlayerRef] = useState<ReactPlayer>();
const [isPlaying, setIsPlaying] = useState(autoPlay);
Expand Down Expand Up @@ -247,6 +244,7 @@ export const ReactPlayerBlock = React.forwardRef<ReactPlayerBlockHandler, ReactP
<button
className={b('button', {theme, text: Boolean(text)}, buttonClassName)}
aria-label={i18n('play')}
ref={buttonRef}
>
{playButtonContent}
</button>
Expand Down Expand Up @@ -365,14 +363,24 @@ export const ReactPlayerBlock = React.forwardRef<ReactPlayerBlockHandler, ReactP
}, [isPlaying, onPlay, onPause]);

const handleClick = useCallback(() => {
buttonRef.current?.click();

if (controls === MediaVideoControlsType.Custom) {
if (customControlsType === CustomControlsType.WithMuteButton) {
changeMute(muted);
} else {
onPlayClick();
}
}
}, [changeMute, customControlsType, muted, onPlayClick, controls]);
}, [controls, customControlsType, changeMute, muted, onPlayClick]);

const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
const key = e.key.toLowerCase();

if (key === 'enter') {
buttonRef.current?.click();
}
}, []);

const onFocusIn = useCallback(() => setHovered(true), []);
const onFocusOut = useCallback(() => setHovered(false), []);
Expand All @@ -394,6 +402,9 @@ export const ReactPlayerBlock = React.forwardRef<ReactPlayerBlockHandler, ReactP
onMouseLeave={onFocusOut}
onFocus={onFocusIn}
onBlur={onFocusOut}
onKeyDown={handleKeyDown}
role="button"
tabIndex={0}
>
{isMounted ? (
<Fragment>
Expand Down
1 change: 1 addition & 0 deletions src/components/Title/TitleItem.scss
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ $block: '.#{$ns}title-item';
}

&__link {
@include reset-button-style();
@include reset-link-style();
@include reset-link-hover();
@include focusable();
Expand Down
8 changes: 2 additions & 6 deletions src/components/Title/TitleItem.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
// TODO fix in https://github.com/gravity-ui/page-constructor/issues/965

import React, {Fragment, ReactNode, useContext} from 'react';

import {HTML, ToggleArrow} from '../';
Expand Down Expand Up @@ -97,9 +93,9 @@ const TitleItem = (props: TitleItemFullProps) => {
);
} else if (onClick) {
content = (
<span className={b('link')} onClick={onClick} title={urlTitle}>
<button className={b('link')} onClick={onClick} title={urlTitle}>
{insideClickableContent}
</span>
</button>
);
}

Expand Down
22 changes: 15 additions & 7 deletions src/components/VideoBlock/VideoBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
// TODO fix in https://github.com/gravity-ui/page-constructor/issues/965

import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';

import {PlayFill} from '@gravity-ui/icons';
import {Icon} from '@gravity-ui/uikit';
import {Icon, useActionHandlers, useUniqId} from '@gravity-ui/uikit';
import debounce from 'lodash/debounce';
import {v4 as uuidv4} from 'uuid';

Expand Down Expand Up @@ -65,6 +61,7 @@ export interface VideoBlockProps extends AnalyticsEventsBase {
className?: string;
previewImg?: string;
playButton?: React.ReactNode;
playButtonId?: string;
height?: number;
fullscreen?: boolean;
autoplay?: boolean;
Expand All @@ -81,6 +78,7 @@ const VideoBlock = (props: VideoBlockProps) => {
id,
previewImg,
playButton,
playButtonId,
height,
fullscreen,
analyticsEvents,
Expand All @@ -94,6 +92,7 @@ const VideoBlock = (props: VideoBlockProps) => {
const [hidePreview, setHidePreview] = useState(false);
const [currentHeight, setCurrentHeight] = useState(height || undefined);
const fullId = useMemo(() => id || uuidv4(), [id]);
const buttonId = useUniqId();

const [isPlaying, setIsPlaying] = useState(!previewImg);

Expand All @@ -113,6 +112,8 @@ const VideoBlock = (props: VideoBlockProps) => {
setTimeout(() => setHidePreview(true), AUTOPLAY_DELAY);
}, [handleAnalytics, analyticsEvents]);

const {onKeyDown: onPreviewKeyDown} = useActionHandlers(onPreviewClick);

useEffect(() => {
const updateSize = debounce(() => {
setCurrentHeight(
Expand Down Expand Up @@ -155,15 +156,22 @@ const VideoBlock = (props: VideoBlockProps) => {
<div className={b(null, className)} style={{height: currentHeight}} ref={ref}>
{iframeContent}
{previewImg && !hidePreview && !fullscreen && (
<div className={b('preview')} onClick={onPreviewClick}>
<div
className={b('preview')}
onClick={onPreviewClick}
onKeyDown={onPreviewKeyDown}
role="button"
tabIndex={0}
aria-labelledby={playButton ? playButtonId : buttonId}
>
<Image
src={previewImg}
className={b('image')}
containerClassName={b('image-wrapper')}
onLoad={onImageLoad}
/>
{playButton || (
<button title="Play" className={b('button')}>
<button title="Play" id={buttonId} className={b('button')}>
<Icon className={b('icon')} data={PlayFill} size={24} />
</button>
)}
Expand Down
2 changes: 2 additions & 0 deletions src/editor/components/AddBlock/AddBlock.scss
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,12 @@ $block: '.#{$ns}add-block';
}

#{$block}__block {
@include reset-button-style();
@include control();

margin-top: $indentS;
justify-content: flex-start;
text-align: start;
cursor: pointer;

&:first-child {
Expand Down
8 changes: 2 additions & 6 deletions src/editor/components/AddBlock/AddBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
// TODO fix in https://github.com/gravity-ui/page-constructor/issues/965

import React, {PropsWithChildren, useEffect, useMemo, useRef, useState} from 'react';

import {Plus} from '@gravity-ui/icons';
Expand Down Expand Up @@ -91,7 +87,7 @@ const AddBlock = ({onAdd, className}: PropsWithChildren<AddBlockProps>) => {
blockData.preview;

return (
<div
<button
key={blockName}
className={b('block')}
onClick={() => {
Expand All @@ -110,7 +106,7 @@ const AddBlock = ({onAdd, className}: PropsWithChildren<AddBlockProps>) => {
</p>
)}
</div>
</div>
</button>
);
})}
</div>
Expand Down
1 change: 1 addition & 0 deletions src/editor/components/EditBlock/EditBlock.scss
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ $block: '.#{$ns}edit-block';
}

&__control {
@include reset-button-style();
@include control($hoverScale: 1.1);

width: $controlIconWidth;
Expand Down
30 changes: 21 additions & 9 deletions src/editor/components/EditBlock/EditBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
// TODO fix in https://github.com/gravity-ui/page-constructor/issues/965

import React, {useEffect, useRef} from 'react';
import React, {useEffect, useMemo, useRef} from 'react';

import {ChevronDown, ChevronUp, Copy as CopyIcon, TrashBin} from '@gravity-ui/icons';
import {useActionHandlers} from '@gravity-ui/uikit';

import {block} from '../../../utils';
import {EditBlockProps} from '../../types';
Expand Down Expand Up @@ -48,6 +45,13 @@ const EditBlock = ({
}: EditBlockProps) => {
const ref = useRef<HTMLDivElement>(null);

const stopPropagationProps = useMemo(
() => ({onClick: (e: React.MouseEvent) => e.stopPropagation()}),
[],
);

const {onKeyDown} = useActionHandlers(onSelect);

useEffect(() => {
if (isActive && ref.current) {
//TODO: add behavior 'smooth' after addiiton of dynamic form layout open/close managing support
Expand All @@ -56,7 +60,15 @@ const EditBlock = ({
}, [isActive]);

return (
<div className={b({active: isActive})} onClick={onSelect} ref={ref}>
<div
className={b({active: isActive})}
onClick={onSelect}
onKeyDown={onKeyDown}
ref={ref}
role="button"
aria-current={isActive}
tabIndex={0}
>
<div
className={b('controls', {
active: isActive,
Expand All @@ -65,18 +77,18 @@ const EditBlock = ({
})}
>
{isActive && (
<div className={b('controls-content')} onClick={(e) => e.stopPropagation()}>
<div className={b('controls-content')} {...stopPropagationProps}>
{actionsOrder.map((action) => {
const Icon = editBlockControlsIcons[action];

return actions[action] ? (
<div
<button
key={action}
className={b('control')}
onClick={actions[action]}
>
<Icon />
</div>
</button>
) : null;
})}
</div>
Expand Down
17 changes: 12 additions & 5 deletions src/navigation/__stories__/CustomComponent/CustomComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
// TODO fix in https://github.com/gravity-ui/page-constructor/issues/965

import React from 'react';

import {useActionHandlers} from '@gravity-ui/uikit';

import {cn} from '../../../utils';
import {NavigationItemProps} from '../../models';

Expand All @@ -18,8 +16,17 @@ type DCDropdownNavigationItemProps = Pick<

export const CustomComponent: React.FC<DCDropdownNavigationItemProps> = (props) => {
const {onClick, isActive, menuLayout} = props;

const {onKeyDown} = useActionHandlers(onClick);

return (
<div className={b({active: isActive})} onClick={onClick}>
<div
className={b({active: isActive})}
onClick={onClick}
onKeyDown={onKeyDown}
tabIndex={onClick ? 0 : -1}
role={onClick ? 'button' : 'group'}
>
{`Custom Item (${menuLayout}${isActive ? ' - active' : ''})`}
</div>
);
Expand Down

0 comments on commit e5378e9

Please sign in to comment.