diff --git a/src/components/ActionTooltip/ActionTooltip.tsx b/src/components/ActionTooltip/ActionTooltip.tsx index ad2b5e38b9..63c573f72c 100644 --- a/src/components/ActionTooltip/ActionTooltip.tsx +++ b/src/components/ActionTooltip/ActionTooltip.tsx @@ -9,13 +9,18 @@ import {Hotkey} from '../Hotkey'; import type {HotkeyProps} from '../Hotkey'; import {Popup} from '../Popup'; import type {PopupPlacement} from '../Popup'; -import type {DOMProps, QAProps} from '../types'; +import type {AriaLabelingProps, DOMProps, QAProps} from '../types'; import {block} from '../utils/cn'; +import {filterDOMProps} from '../utils/filterDOMProps'; import {getElementRef} from '../utils/getElementRef'; import './ActionTooltip.scss'; -export interface ActionTooltipProps extends QAProps, DOMProps, TooltipDelayProps { +export interface ActionTooltipProps + extends AriaLabelingProps, + QAProps, + DOMProps, + TooltipDelayProps { id?: string; disablePortal?: boolean; contentClassName?: string; @@ -44,15 +49,18 @@ export function ActionTooltip(props: ActionTooltipProps) { qa, id, disablePortal, - ...delayProps + openDelay, + closeDelay, + ...otherProps } = props; const [anchorElement, setAnchorElement] = React.useState(null); - const tooltipVisible = useTooltipVisible(anchorElement, delayProps); + const tooltipVisible = useTooltipVisible(anchorElement, {openDelay, closeDelay}); const renderPopup = () => { return ( { return ( -
+
{typeof renderNote === 'function' && ( { onClose, align, qa, + ...otherProps } = props; return ( ; -export interface AlertProps extends QAProps, Partial { +export interface AlertProps extends AriaLabelingProps, QAProps, Partial { title?: React.ReactNode; message?: React.ReactNode; theme?: AlertTheme; diff --git a/src/components/ArrowToggle/ArrowToggle.tsx b/src/components/ArrowToggle/ArrowToggle.tsx index a13bb4cff1..c6a715aead 100644 --- a/src/components/ArrowToggle/ArrowToggle.tsx +++ b/src/components/ArrowToggle/ArrowToggle.tsx @@ -3,12 +3,13 @@ import React from 'react'; import {ChevronDown} from '@gravity-ui/icons'; import {Icon} from '../Icon'; -import type {QAProps} from '../types'; +import type {AriaLabelingProps, QAProps} from '../types'; import {block} from '../utils/cn'; +import {filterDOMProps} from '../utils/filterDOMProps'; import './ArrowToggle.scss'; -export interface ArrowToggleProps extends QAProps { +export interface ArrowToggleProps extends AriaLabelingProps, QAProps { size?: number; direction?: 'top' | 'left' | 'bottom' | 'right'; className?: string; @@ -16,9 +17,16 @@ export interface ArrowToggleProps extends QAProps { const b = block('arrow-toggle'); -export function ArrowToggle({size = 16, direction = 'bottom', className, qa}: ArrowToggleProps) { +export function ArrowToggle({ + size = 16, + direction = 'bottom', + className, + qa, + ...otherProps +}: ArrowToggleProps) { return ( ((props, ref) backgroundColor, borderColor, title, - 'aria-label': ariaLabel, - 'aria-labelledby': ariaLabelledby, className, style: styleProp, qa, + ...otherProps } = props; const style = {backgroundColor, color: borderColor, ...styleProp}; @@ -72,11 +72,10 @@ export const Avatar = React.forwardRef((props, ref) return (
; diff --git a/src/components/AvatarStack/AvatarStackMore.tsx b/src/components/AvatarStack/AvatarStackMore.tsx index 1ee09fcf91..7980b4e837 100644 --- a/src/components/AvatarStack/AvatarStackMore.tsx +++ b/src/components/AvatarStack/AvatarStackMore.tsx @@ -2,6 +2,7 @@ import React from 'react'; import {DEFAULT_AVATAR_SIZE} from '../Avatar'; import {block} from '../utils/cn'; +import {filterDOMProps} from '../utils/filterDOMProps'; import i18n from './i18n'; import type {AvatarStackMoreProps} from './types'; @@ -16,13 +17,15 @@ export const AvatarStackMore = React.forwardRef (
{ return ( diff --git a/src/components/AvatarStack/types.ts b/src/components/AvatarStack/types.ts index 8266312288..a593f964c3 100644 --- a/src/components/AvatarStack/types.ts +++ b/src/components/AvatarStack/types.ts @@ -1,6 +1,7 @@ import type React from 'react'; import type {AvatarSize} from '../Avatar'; +import type {AriaLabelingProps} from '../types'; export type AvatarStackOverlapSize = 's' | 'm' | 'l'; @@ -42,14 +43,12 @@ export interface AvatarStackProps { renderMore?: (options: {count: number}) => React.ReactElement; } -export type AvatarStackMoreProps = Pick< - React.HTMLProps, - 'className' | 'aria-label' -> & { - count: number; - size?: AvatarSize; - borderColor?: string; -}; +export type AvatarStackMoreProps = Pick, 'className'> & + AriaLabelingProps & { + count: number; + size?: AvatarSize; + borderColor?: string; + }; export type AvatarStackMoreButtonProps = Pick, 'onClick'> & AvatarStackMoreProps & { diff --git a/src/components/DefinitionList/DefinitionList.tsx b/src/components/DefinitionList/DefinitionList.tsx index 7eeaecce78..0bed064965 100644 --- a/src/components/DefinitionList/DefinitionList.tsx +++ b/src/components/DefinitionList/DefinitionList.tsx @@ -1,5 +1,6 @@ import React from 'react'; +import {filterDOMProps} from '../utils/filterDOMProps'; import {isOfType} from '../utils/isOfType'; import {warnOnce} from '../utils/warn'; @@ -18,6 +19,7 @@ export function DefinitionList({ className, children, qa, + ...otherProps }: DefinitionListProps) { const normalizedChildren = prepareChildren(children); return ( @@ -27,6 +29,7 @@ export function DefinitionList({ contentMaxWidth={contentMaxWidth} >
diff --git a/src/components/DefinitionList/types.ts b/src/components/DefinitionList/types.ts index 4cda2b3267..dc21662ee2 100644 --- a/src/components/DefinitionList/types.ts +++ b/src/components/DefinitionList/types.ts @@ -1,7 +1,7 @@ import type React from 'react'; import type {HelpMarkProps} from '../HelpMark'; -import type {QAProps} from '../types'; +import type {AriaLabelingProps, QAProps} from '../types'; export type DefinitionListItemNote = string | HelpMarkProps; export interface DefinitionListItemProps { @@ -13,7 +13,7 @@ export interface DefinitionListItemProps { export type DefinitionListDirection = 'vertical' | 'horizontal'; -export interface DefinitionListProps extends QAProps { +export interface DefinitionListProps extends AriaLabelingProps, QAProps { responsive?: boolean; direction?: DefinitionListDirection; nameMaxWidth?: number; diff --git a/src/components/Dialog/Dialog.tsx b/src/components/Dialog/Dialog.tsx index 1acdc56547..a7ee1c7025 100644 --- a/src/components/Dialog/Dialog.tsx +++ b/src/components/Dialog/Dialog.tsx @@ -4,8 +4,9 @@ import React from 'react'; import {Modal} from '../Modal'; import type {ModalCloseReason, ModalProps} from '../Modal'; -import type {QAProps} from '../types'; +import type {AriaLabelingProps, QAProps} from '../types'; import {block} from '../utils/cn'; +import {filterDOMProps} from '../utils/filterDOMProps'; import {ButtonClose} from './ButtonClose/ButtonClose'; import {DialogBody} from './DialogBody/DialogBody'; @@ -17,7 +18,7 @@ import './Dialog.scss'; const b = block('dialog'); -interface DialogOwnProps extends QAProps { +interface DialogOwnProps extends AriaLabelingProps, QAProps { open: boolean; children: React.ReactNode; onEscapeKeyDown?: ModalProps['onEscapeKeyDown']; @@ -34,8 +35,6 @@ interface DialogOwnProps extends QAProps { className?: string; modalClassName?: string; size?: 's' | 'm' | 'l'; - 'aria-label'?: string; - 'aria-labelledby'?: string; container?: HTMLElement; disableFocusTrap?: boolean; disableAutoFocus?: boolean; @@ -93,13 +92,13 @@ export class Dialog extends React.Component { onTransitionEntered, onTransitionExit, onTransitionExited, - 'aria-label': ariaLabel, - 'aria-labelledby': ariaLabelledBy, qa, + ...otherProps } = this.props; return ( { onTransitionExit={onTransitionExit} onTransitionExited={onTransitionExited} className={b('modal', modalClassName)} - aria-label={ariaLabel} - aria-labelledby={ariaLabelledBy} container={container} qa={qa} > diff --git a/src/components/Divider/Divider.tsx b/src/components/Divider/Divider.tsx index bfade0711f..6031120f9e 100644 --- a/src/components/Divider/Divider.tsx +++ b/src/components/Divider/Divider.tsx @@ -1,14 +1,15 @@ import React from 'react'; -import type {DOMProps, QAProps} from '../types'; +import type {AriaLabelingProps, DOMProps, QAProps} from '../types'; import {block} from '../utils/cn'; +import {filterDOMProps} from '../utils/filterDOMProps'; import './Divider.scss'; export type DividerOrientation = 'vertical' | 'horizontal'; export type DividerAlign = 'start' | 'center' | 'end'; -export interface DividerProps extends DOMProps, QAProps { +export interface DividerProps extends AriaLabelingProps, DOMProps, QAProps { orientation?: DividerOrientation; align?: DividerAlign; children?: React.ReactNode; @@ -17,10 +18,19 @@ export interface DividerProps extends DOMProps, QAProps { const b = block('divider'); export const Divider = React.forwardRef(function Divider(props, ref) { - const {orientation = 'horizontal', className, style, qa, children, align = 'start'} = props; + const { + orientation = 'horizontal', + className, + style, + qa, + children, + align = 'start', + ...otherProps + } = props; return (
(function Hotkey(props, ref) { - const {value, platform, view = 'light', qa, style, className} = props; + const {value, platform, view = 'light', qa, style, className, ...otherProps} = props; const groups = parseHotkeys(value, {platform}); const content: React.ReactNode[] = []; @@ -64,7 +65,13 @@ export const Hotkey = React.forwardRef(function Hotkey if (content.length === 0) return null; return ( - + {content} ); diff --git a/src/components/Label/Label.tsx b/src/components/Label/Label.tsx index f217390805..a04c013200 100644 --- a/src/components/Label/Label.tsx +++ b/src/components/Label/Label.tsx @@ -8,8 +8,9 @@ import {ClipboardIcon} from '../ClipboardIcon'; import {CopyToClipboard} from '../CopyToClipboard'; import type {CopyToClipboardStatus} from '../CopyToClipboard'; import {Icon} from '../Icon'; -import type {QAProps} from '../types'; +import type {AriaLabelingProps, QAProps} from '../types'; import {block} from '../utils/cn'; +import {filterDOMProps} from '../utils/filterDOMProps'; import './Label.scss'; @@ -23,7 +24,7 @@ const sizeMap: Record = { m: {copyIconSize: 16, closeIconSize: 16}, }; -export interface LabelProps extends QAProps { +export interface LabelProps extends AriaLabelingProps, QAProps { /** Label icon (at start) */ icon?: React.ReactNode; /** Disabled state */ @@ -80,6 +81,7 @@ export const Label = React.forwardRef(function Label( onCopy, onClick, qa, + ...otherProps } = props; const hasContent = Boolean(children !== '' && React.Children.count(children) > 0); @@ -145,6 +147,7 @@ export const Label = React.forwardRef(function Label( return (
(function Menu( - {size = 'm', children, style, className, qa}, + {size = 'm', children, style, className, qa, ...otherProps}, ref, ) { return (
    ; children?: React.ReactNode; - /** - * Id of visible `` caption element - */ - 'aria-labelledby'?: string; - /** - * A11y text - * Prefer `aria-labelledby` in case caption is visible to user - */ - 'aria-label'?: string; container?: HTMLElement; contentClassName?: string; onTransitionEnter?: VoidFunction; @@ -75,10 +67,9 @@ export function Modal({ contentOverflow = 'visible', className, contentClassName, - 'aria-labelledby': ariaLabelledBy, - 'aria-label': ariaLabel, container, qa, + ...otherProps }: ModalProps) { const containerRef = React.useRef(null); const contentRef = React.useRef(null); @@ -138,12 +129,11 @@ export function Modal({ autoFocus={!disableAutoFocus && autoFocus} >
    +
    {children &&
    {children}
    }
    diff --git a/src/components/Pagination/Pagination.tsx b/src/components/Pagination/Pagination.tsx index 8d740539e6..1e31bb0792 100644 --- a/src/components/Pagination/Pagination.tsx +++ b/src/components/Pagination/Pagination.tsx @@ -4,6 +4,7 @@ import React from 'react'; import {useMobile} from '../mobile'; import {block} from '../utils/cn'; +import {filterDOMProps} from '../utils/filterDOMProps'; import { PaginationButton, @@ -33,6 +34,7 @@ export const Pagination = ({ showInput = false, className, qa, + ...otherProps }: PaginationProps) => { const mobile = useMobile(); @@ -109,7 +111,11 @@ export const Pagination = ({ .filter(Boolean); return ( -
    +
    {pagination} {showInput && ( ; - /** `aria-label` attribute, use this attribute only if you didn't have visible caption */ - 'aria-label'?: React.AriaAttributes['aria-label']; - /** `aria-labelledby` attribute, prefer this attribute if you have visible caption */ - 'aria-labelledby'?: React.AriaAttributes['aria-labelledby']; /** `aria-modal` attribute, default value is equal to focusTrap */ 'aria-modal'?: React.AriaAttributes['aria-modal']; /** `aria-role` attribute */ @@ -111,13 +113,12 @@ export function Popup({ qa, restoreFocus, restoreFocusRef, - 'aria-label': ariaLabel, - 'aria-labelledby': ariaLabelledBy, role: roleProp, id, focusTrap = false, autoFocus = false, 'aria-modal': ariaModal = focusTrap, + ...otherProps }: PopupProps) { const containerRef = React.useRef(null); @@ -184,6 +185,7 @@ export function Popup({ >
    diff --git a/src/components/Progress/Progress.tsx b/src/components/Progress/Progress.tsx index de452af685..0d28f4708b 100644 --- a/src/components/Progress/Progress.tsx +++ b/src/components/Progress/Progress.tsx @@ -1,5 +1,7 @@ import React from 'react'; +import {filterDOMProps} from '../utils/filterDOMProps'; + import {ProgressWithStack} from './ProgressWithStack'; import {ProgressWithValue} from './ProgressWithValue'; import {progressBlock} from './constants'; @@ -14,7 +16,12 @@ export const Progress = React.forwardRef( const resolvedProps: ProgressProps = {...props, text, theme, size, loading}; return ( -
    +
    {text}
    {isProgressWithStack(resolvedProps) ? ( diff --git a/src/components/Progress/types.ts b/src/components/Progress/types.ts index faa4cde9d0..077de95597 100644 --- a/src/components/Progress/types.ts +++ b/src/components/Progress/types.ts @@ -1,6 +1,6 @@ import type React from 'react'; -import type {QAProps} from '../types'; +import type {AriaLabelingProps, QAProps} from '../types'; export type ProgressTheme = 'default' | 'success' | 'warning' | 'danger' | 'info' | 'misc'; export type ProgressSize = 'xs' | 's' | 'm'; @@ -21,7 +21,7 @@ export interface ProgressColorStops { stop: number; } -interface ProgressGeneralProps extends QAProps { +interface ProgressGeneralProps extends AriaLabelingProps, QAProps { /** ClassName of element */ className?: string; } diff --git a/src/components/Skeleton/Skeleton.tsx b/src/components/Skeleton/Skeleton.tsx index 1f5eb0f168..48ab0b43f7 100644 --- a/src/components/Skeleton/Skeleton.tsx +++ b/src/components/Skeleton/Skeleton.tsx @@ -1,7 +1,8 @@ import React from 'react'; -import type {QAProps} from '../types'; +import type {AriaLabelingProps, QAProps} from '../types'; import {block} from '../utils/cn'; +import {filterDOMProps} from '../utils/filterDOMProps'; import './Skeleton.scss'; @@ -9,8 +10,16 @@ const b = block('skeleton'); export interface SkeletonProps extends Pick, 'className' | 'style'>, + AriaLabelingProps, QAProps {} -export function Skeleton({className, style, qa}: SkeletonProps) { - return
    ; +export function Skeleton({className, style, qa, ...otherProps}: SkeletonProps) { + return ( +
    + ); } diff --git a/src/components/Spin/Spin.tsx b/src/components/Spin/Spin.tsx index 4b8e2b3a3b..27214ea3ca 100644 --- a/src/components/Spin/Spin.tsx +++ b/src/components/Spin/Spin.tsx @@ -1,7 +1,8 @@ import React from 'react'; -import type {DOMProps, QAProps} from '../types'; +import type {AriaLabelingProps, DOMProps, QAProps} from '../types'; import {block} from '../utils/cn'; +import {filterDOMProps} from '../utils/filterDOMProps'; import './Spin.scss'; @@ -9,15 +10,21 @@ const b = block('spin'); export type SpinSize = 'xs' | 's' | 'm' | 'l' | 'xl'; -export interface SpinProps extends DOMProps, QAProps { +export interface SpinProps extends AriaLabelingProps, DOMProps, QAProps { size?: SpinSize; } export const Spin = React.forwardRef(function Spin(props, ref) { - const {size = 'm', style, className, qa} = props; + const {size = 'm', style, className, qa, ...otherProps} = props; return ( -
    +
    ); diff --git a/src/components/Table/Table.tsx b/src/components/Table/Table.tsx index 284ff0020d..acfdbe6d72 100644 --- a/src/components/Table/Table.tsx +++ b/src/components/Table/Table.tsx @@ -6,8 +6,9 @@ import _get from 'lodash/get'; import _has from 'lodash/has'; import _isNumber from 'lodash/isNumber'; -import type {QAProps} from '../types'; +import type {AriaLabelingProps, QAProps} from '../types'; import {block} from '../utils/cn'; +import {filterDOMProps} from '../utils/filterDOMProps'; import {warnOnce} from '../utils/warn'; import i18n from './i18n'; @@ -95,7 +96,7 @@ export interface DescriptorType { export type TableWidth = 'auto' | 'max'; // TODO: Replace @default in props description with defaultProps in order to work with Storybook. -export interface TableProps extends QAProps { +export interface TableProps extends AriaLabelingProps, QAProps { /** Data */ data: I[]; /** Column parameters */ @@ -456,7 +457,11 @@ export class Table> extends Rea private renderTable() { const {width = 'auto'} = this.props; return ( - +
    {this.renderHead()} {this.renderBody()}
    diff --git a/src/components/Tabs/Tabs.tsx b/src/components/Tabs/Tabs.tsx index e0f1fd907a..f61e581ca0 100644 --- a/src/components/Tabs/Tabs.tsx +++ b/src/components/Tabs/Tabs.tsx @@ -2,8 +2,9 @@ import React from 'react'; -import type {QAProps} from '../types'; +import type {AriaLabelingProps, QAProps} from '../types'; import {block} from '../utils/cn'; +import {filterDOMProps} from '../utils/filterDOMProps'; import {TabsContext} from './TabsContext'; import {TabsItem} from './TabsItem'; @@ -23,7 +24,7 @@ export type TabsSize = 'm' | 'l' | 'xl'; export interface TabsItemProps extends Omit {} -export interface TabsProps extends QAProps { +export interface TabsProps extends AriaLabelingProps, QAProps { /** * Tabs direction * @deprecated Vertical tabs are deprecated @@ -78,6 +79,7 @@ const TabsComponent = React.forwardRef( onSelectTab, wrapTo, qa, + ...otherProps }, ref, ) => { @@ -104,7 +106,13 @@ const TabsComponent = React.forwardRef( }, [items, onSelectTab, wrapTo]); return ( -
    +
    {children || tabs} diff --git a/src/components/Toc/Toc.tsx b/src/components/Toc/Toc.tsx index a29575dbe1..a8759a5ea2 100644 --- a/src/components/Toc/Toc.tsx +++ b/src/components/Toc/Toc.tsx @@ -1,7 +1,8 @@ import React from 'react'; -import type {QAProps} from '../types'; +import type {AriaLabelingProps, QAProps} from '../types'; import {block} from '../utils/cn'; +import {filterDOMProps} from '../utils/filterDOMProps'; import {TocItem} from './TocItem/TocItem'; import type {TocItem as TocItemType} from './types'; @@ -10,7 +11,7 @@ import './Toc.scss'; const b = block('toc'); -export interface TocProps extends QAProps { +export interface TocProps extends AriaLabelingProps, QAProps { className?: string; items: TocItemType[]; value?: string; @@ -18,10 +19,15 @@ export interface TocProps extends QAProps { } export const Toc = React.forwardRef(function Toc(props, ref) { - const {value: activeValue, items, className, onUpdate, qa} = props; + const {value: activeValue, items, className, onUpdate, qa, ...otherProps} = props; return ( -