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

fix: eslint a11y rules #1079

Merged
merged 2 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
Loading