diff --git a/packages/vkui/src/components/Alert/Alert.tsx b/packages/vkui/src/components/Alert/Alert.tsx index d181583fa1..f6a2db52c6 100644 --- a/packages/vkui/src/components/Alert/Alert.tsx +++ b/packages/vkui/src/components/Alert/Alert.tsx @@ -180,7 +180,7 @@ export const Alert = ({ onItemClick={onItemClick} /> {isDismissButtonVisible && dismissButtonMode === 'outside' && ( - + {dismissLabel} )} diff --git a/packages/vkui/src/components/BaseGallery/types.ts b/packages/vkui/src/components/BaseGallery/types.ts index 5d515752d7..332ceae926 100644 --- a/packages/vkui/src/components/BaseGallery/types.ts +++ b/packages/vkui/src/components/BaseGallery/types.ts @@ -47,4 +47,12 @@ export interface BaseGalleryProps showArrows?: boolean; hasPointer?: boolean; arrowSize?: ScrollArrowProps['size']; + /** + * Текст для кнопки-стрелки влево (назад). Делает ее доступной для ассистивных технологий + */ + arrowPrevLabel?: string; + /** + * Текст для кнопки-стрелки вправо (вперед). Делает ее доступной для ассистивных технологий + */ + arrowNextLabel?: string; } diff --git a/packages/vkui/src/components/Calendar/Calendar.tsx b/packages/vkui/src/components/Calendar/Calendar.tsx index 0f8c28981d..105f87c367 100644 --- a/packages/vkui/src/components/Calendar/Calendar.tsx +++ b/packages/vkui/src/components/Calendar/Calendar.tsx @@ -14,13 +14,13 @@ import styles from './Calendar.module.css'; export interface CalendarProps extends Omit, 'onChange'>, - Pick, + Pick, Pick< CalendarHeaderProps, - | 'prevMonthAriaLabel' - | 'nextMonthAriaLabel' - | 'changeMonthAriaLabel' - | 'changeYearAriaLabel' + | 'prevMonthLabel' + | 'nextMonthLabel' + | 'changeMonthLabel' + | 'changeYearLabel' | 'onNextMonth' | 'onPrevMonth' | 'prevMonthIcon' @@ -35,7 +35,7 @@ export interface CalendarProps enableTime?: boolean; disablePickers?: boolean; doneButtonText?: string; - changeDayAriaLabel?: string; + changeDayLabel?: string; weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6; showNeighboringMonth?: boolean; size?: 's' | 'm'; @@ -77,14 +77,14 @@ export const Calendar = ({ doneButtonText, weekStartsOn = 1, disablePickers, - changeHoursAriaLabel, - changeMinutesAriaLabel, - prevMonthAriaLabel, - nextMonthAriaLabel, - changeMonthAriaLabel, - changeYearAriaLabel, + changeHoursLabel = 'Изменить час', + changeMinutesLabel = 'Изменить минуту', + prevMonthLabel = 'Предыдущий месяц', + nextMonthLabel = 'Следующий месяц', + changeMonthLabel = 'Изменить месяц', + changeYearLabel = 'Изменить год', showNeighboringMonth, - changeDayAriaLabel = 'Изменить день', + changeDayLabel = 'Изменить день', size = 'm', viewDate: externalViewDate, onHeaderChange, @@ -180,10 +180,10 @@ export const Calendar = ({ onPrevMonth={setPrevMonth} disablePickers={disablePickers || size === 's'} className={styles['Calendar__header']} - prevMonthAriaLabel={prevMonthAriaLabel} - nextMonthAriaLabel={nextMonthAriaLabel} - changeMonthAriaLabel={changeMonthAriaLabel} - changeYearAriaLabel={changeYearAriaLabel} + prevMonthLabel={prevMonthLabel} + nextMonthLabel={nextMonthLabel} + changeMonthLabel={changeMonthLabel} + changeYearLabel={changeYearLabel} prevMonthIcon={prevMonthIcon} nextMonthIcon={nextMonthIcon} prevMonthProps={prevMonthProps} @@ -195,7 +195,7 @@ export const Calendar = ({ weekStartsOn={weekStartsOn} isDayFocused={isDayFocused} tabIndex={0} - aria-label={changeDayAriaLabel} + aria-label={changeDayLabel} onKeyDown={handleKeyDown} onDayChange={onDayChange} isDayActive={isDayActive} @@ -215,8 +215,8 @@ export const Calendar = ({ onChange={onChange} onClose={onClose} doneButtonText={doneButtonText} - changeHoursAriaLabel={changeHoursAriaLabel} - changeMinutesAriaLabel={changeMinutesAriaLabel} + changeHoursLabel={changeHoursLabel} + changeMinutesLabel={changeMinutesLabel} isDayDisabled={minDateTime || maxDateTime ? isDayDisabled : undefined} /> diff --git a/packages/vkui/src/components/CalendarDay/CalendarDay.tsx b/packages/vkui/src/components/CalendarDay/CalendarDay.tsx index 096137b12e..de6ad0b6bf 100644 --- a/packages/vkui/src/components/CalendarDay/CalendarDay.tsx +++ b/packages/vkui/src/components/CalendarDay/CalendarDay.tsx @@ -3,6 +3,7 @@ import { classNames } from '@vkontakte/vkjs'; import { ENABLE_KEYBOARD_INPUT_EVENT_NAME } from '../../hooks/useKeyboardInputTracker'; import { useConfigProvider } from '../ConfigProvider/ConfigProviderContext'; import { Tappable, TappableElementProps } from '../Tappable/Tappable'; +import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden'; import styles from './CalendarDay.module.css'; export type CalendarDayElementProps = Omit< @@ -50,7 +51,8 @@ export const CalendarDay = React.memo( sameMonth, size, className, - ...props + children, + ...restProps }: CalendarDayProps) => { const { locale } = useConfigProvider(); const ref = React.useRef(null); @@ -58,6 +60,13 @@ export const CalendarDay = React.memo( const handleEnter = React.useCallback(() => onEnter?.(day), [day, onEnter]); const handleLeave = React.useCallback(() => onLeave?.(day), [day, onLeave]); + const label = new Intl.DateTimeFormat(locale, { + weekday: 'long', + year: 'numeric', + month: 'long', + day: 'numeric', + }).format(day); + React.useEffect(() => { if (focused && ref.current) { ref.current.dispatchEvent(new Event(ENABLE_KEYBOARD_INPUT_EVENT_NAME, { bubbles: true })); @@ -66,7 +75,7 @@ export const CalendarDay = React.memo( }, [focused]); if (hidden) { - return
; + return
; } return ( @@ -86,18 +95,12 @@ export const CalendarDay = React.memo( hasActive={false} onClick={onClick} disabled={disabled} - aria-label={new Intl.DateTimeFormat(locale, { - weekday: 'long', - year: 'numeric', - month: 'long', - day: 'numeric', - }).format(day)} tabIndex={-1} getRootRef={ref} focusVisibleMode={active ? 'outside' : 'inside'} onEnter={handleEnter} onLeave={handleLeave} - {...props} + {...restProps} >
-
{day.getDate()}
+
+ {children ?? label} + {day.getDate()} +
diff --git a/packages/vkui/src/components/CalendarHeader/CalendarHeader.tsx b/packages/vkui/src/components/CalendarHeader/CalendarHeader.tsx index 6122143af9..d12b505d6a 100644 --- a/packages/vkui/src/components/CalendarHeader/CalendarHeader.tsx +++ b/packages/vkui/src/components/CalendarHeader/CalendarHeader.tsx @@ -14,6 +14,7 @@ import { CustomSelect } from '../CustomSelect/CustomSelect'; import { RootComponent } from '../RootComponent/RootComponent'; import { Tappable, TappableElementProps } from '../Tappable/Tappable'; import { Paragraph } from '../Typography/Paragraph/Paragraph'; +import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden'; import styles from './CalendarHeader.module.css'; type ArrowMonthProps = Omit; @@ -24,10 +25,10 @@ export interface CalendarHeaderProps prevMonth?: boolean; nextMonth?: boolean; disablePickers?: boolean; - prevMonthAriaLabel?: string; - nextMonthAriaLabel?: string; - changeMonthAriaLabel?: string; - changeYearAriaLabel?: string; + prevMonthLabel?: string; + nextMonthLabel?: string; + changeMonthLabel?: string; + changeYearLabel?: string; prevMonthIcon?: React.ReactNode; nextMonthIcon?: React.ReactNode; prevMonthProps?: ArrowMonthProps; @@ -53,10 +54,10 @@ export const CalendarHeader = ({ onPrevMonth, prevMonthProps = {}, nextMonthProps = {}, - prevMonthAriaLabel = 'Предыдущий месяц', - nextMonthAriaLabel = 'Следующий месяц', - changeMonthAriaLabel = 'Изменить месяц', - changeYearAriaLabel = 'Изменить год', + prevMonthLabel = 'Предыдущий месяц', + nextMonthLabel = 'Следующий месяц', + changeMonthLabel = 'Изменить месяц', + changeYearLabel = 'Изменить год', prevMonthIcon = ( + + {prevMonthLabel}, {formatter.format(subMonths(viewDate, 1))} + {prevMonthIcon} @@ -163,7 +166,7 @@ export const CalendarHeader = ({ onChange={onMonthsChange} forceDropdownPortal={false} selectType="accent" - aria-label={changeMonthAriaLabel} + aria-label={changeMonthLabel} /> @@ -192,9 +195,11 @@ export const CalendarHeader = ({ nextMonthClassName, )} onClick={onNextMonth} - aria-label={`${nextMonthAriaLabel}, ${formatter.format(addMonths(viewDate, 1))}`} {...restNextMonthProps} > + + {nextMonthLabel}, {formatter.format(addMonths(viewDate, 1))} + {nextMonthIcon} diff --git a/packages/vkui/src/components/CalendarRange/CalendarRange.tsx b/packages/vkui/src/components/CalendarRange/CalendarRange.tsx index 730d586465..958b7855e5 100644 --- a/packages/vkui/src/components/CalendarRange/CalendarRange.tsx +++ b/packages/vkui/src/components/CalendarRange/CalendarRange.tsx @@ -21,10 +21,10 @@ export interface CalendarRangeProps extends Omit, 'onChange'>, Pick< CalendarHeaderProps, - | 'prevMonthAriaLabel' - | 'nextMonthAriaLabel' - | 'changeMonthAriaLabel' - | 'changeYearAriaLabel' + | 'prevMonthLabel' + | 'nextMonthLabel' + | 'changeMonthLabel' + | 'changeYearLabel' | 'prevMonthIcon' | 'nextMonthIcon' >, @@ -33,7 +33,7 @@ export interface CalendarRangeProps disablePast?: boolean; disableFuture?: boolean; disablePickers?: boolean; - changeDayAriaLabel?: string; + changeDayLabel?: string; weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6; onChange?(value?: Array): void; shouldDisableDate?(value: Date): boolean; @@ -60,11 +60,11 @@ export const CalendarRange = ({ onClose, weekStartsOn = 1, disablePickers, - prevMonthAriaLabel, - nextMonthAriaLabel, - changeMonthAriaLabel, - changeYearAriaLabel, - changeDayAriaLabel = 'Изменить день', + prevMonthLabel = 'Предыдущий месяц', + nextMonthLabel = 'Следующий месяц', + changeMonthLabel = 'Изменить месяц', + changeYearLabel = 'Изменить год', + changeDayLabel = 'Изменить день', prevMonthIcon, nextMonthIcon, listenDayChangesForUpdate, @@ -187,10 +187,10 @@ export const CalendarRange = ({ onPrevMonth={setPrevMonth} disablePickers={disablePickers} className={styles['CalendarRange__header']} - prevMonthAriaLabel={prevMonthAriaLabel} - nextMonthAriaLabel={nextMonthAriaLabel} - changeMonthAriaLabel={changeMonthAriaLabel} - changeYearAriaLabel={changeYearAriaLabel} + prevMonthLabel={prevMonthLabel} + nextMonthLabel={nextMonthLabel} + changeMonthLabel={changeMonthLabel} + changeYearLabel={changeYearLabel} prevMonthIcon={prevMonthIcon} />
@@ -222,17 +222,17 @@ export const CalendarRange = ({ onNextMonth={setNextMonth} disablePickers={disablePickers} className={styles['CalendarRange__header']} - prevMonthAriaLabel={prevMonthAriaLabel} - nextMonthAriaLabel={nextMonthAriaLabel} - changeMonthAriaLabel={changeMonthAriaLabel} - changeYearAriaLabel={changeYearAriaLabel} + prevMonthLabel={prevMonthLabel} + nextMonthLabel={nextMonthLabel} + changeMonthLabel={changeMonthLabel} + changeYearLabel={changeYearLabel} nextMonthIcon={nextMonthIcon} /> { const localHours = isDayDisabled @@ -72,7 +72,7 @@ export const CalendarTime = ({ options={localHours} onChange={onHoursChange} forceDropdownPortal={false} - aria-label={changeHoursAriaLabel} + aria-label={changeHoursLabel} />
@@ -84,13 +84,13 @@ export const CalendarTime = ({ options={localMinutes} onChange={onMinutesChange} forceDropdownPortal={false} - aria-label={changeMinutesAriaLabel} + aria-label={changeMinutesLabel} />
- diff --git a/packages/vkui/src/components/Cell/Cell.tsx b/packages/vkui/src/components/Cell/Cell.tsx index 59e7e94dca..bdb91d8ebf 100644 --- a/packages/vkui/src/components/Cell/Cell.tsx +++ b/packages/vkui/src/components/Cell/Cell.tsx @@ -40,7 +40,7 @@ export interface CellProps */ onDragFinish?(swappedItemRange: SwappedItemRange): void; /** - * aria-label для кнопки перетаскивания ячейки + * Текст для кнопки перетаскивания ячейки */ draggerLabel?: string; } @@ -84,11 +84,12 @@ export const Cell = ({ + > + {draggerLabel} + ) : null; let checkbox; diff --git a/packages/vkui/src/components/Cell/CellDragger/CellDragger.tsx b/packages/vkui/src/components/Cell/CellDragger/CellDragger.tsx index b6ebb543de..c730f66b12 100644 --- a/packages/vkui/src/components/Cell/CellDragger/CellDragger.tsx +++ b/packages/vkui/src/components/Cell/CellDragger/CellDragger.tsx @@ -10,6 +10,7 @@ import { usePlatform } from '../../../hooks/usePlatform'; import { useIsomorphicLayoutEffect } from '../../../lib/useIsomorphicLayoutEffect'; import { HTMLAttributesWithRootRef } from '../../../types'; import { Touch } from '../../Touch/Touch'; +import { VisuallyHidden } from '../../VisuallyHidden/VisuallyHidden'; import styles from './CellDragger.module.css'; interface CellDraggerProps @@ -25,6 +26,7 @@ export const CellDragger = ({ className, onDragStateChange, onDragFinish, + children, ...restProps }: CellDraggerProps) => { const platform = usePlatform(); @@ -49,6 +51,7 @@ export const CellDragger = ({ onEnd={disabled ? undefined : onDragEnd} {...restProps} > + {children && {children}} ); diff --git a/packages/vkui/src/components/Chip/Chip.tsx b/packages/vkui/src/components/Chip/Chip.tsx index fc91edb39c..94cd17aa68 100644 --- a/packages/vkui/src/components/Chip/Chip.tsx +++ b/packages/vkui/src/components/Chip/Chip.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { Icon16Cancel } from '@vkontakte/icons'; import { classNames, hasReactNode, noop } from '@vkontakte/vkjs'; import { useAdaptivity } from '../../hooks/useAdaptivity'; -import { getTitleFromChildren } from '../../lib/utils'; +import { getTextFromChildren } from '../../lib/children'; import { HTMLAttributesWithRootRef } from '../../types'; import { RootComponent } from '../RootComponent/RootComponent'; import { Tappable } from '../Tappable/Tappable'; @@ -58,7 +58,7 @@ export const Chip = ({ }, [onRemove, value], ); - const title = getTitleFromChildren(children); + const title = getTextFromChildren(children); return ( + ) : ( - + ) @@ -249,7 +249,7 @@ export const DateInput = ({ index={0} onElementSelect={setFocusedElement} value={internalValue[0]} - aria-label={changeDayAriaLabel} + label={changeDayLabel} /> . . {enableTime && ( @@ -280,7 +280,7 @@ export const DateInput = ({ index={3} onElementSelect={setFocusedElement} value={internalValue[3]} - aria-label={changeHoursAriaLabel} + label={changeHoursLabel} /> : )} @@ -307,13 +307,13 @@ export const DateInput = ({ getRootRef={calendarRef} doneButtonText={doneButtonText} disablePickers={disablePickers} - changeHoursAriaLabel={changeHoursAriaLabel} - changeMinutesAriaLabel={changeMinutesAriaLabel} - prevMonthAriaLabel={prevMonthAriaLabel} - nextMonthAriaLabel={nextMonthAriaLabel} - changeMonthAriaLabel={changeMonthAriaLabel} - changeYearAriaLabel={changeYearAriaLabel} - changeDayAriaLabel={changeDayAriaLabel} + changeHoursLabel={changeHoursLabel} + changeMinutesLabel={changeMinutesLabel} + prevMonthLabel={prevMonthLabel} + nextMonthLabel={nextMonthLabel} + changeMonthLabel={changeMonthLabel} + changeYearLabel={changeYearLabel} + changeDayLabel={changeDayLabel} showNeighboringMonth={showNeighboringMonth} size={size} viewDate={viewDate} diff --git a/packages/vkui/src/components/DateRangeInput/DateRangeInput.tsx b/packages/vkui/src/components/DateRangeInput/DateRangeInput.tsx index 5da6ad8b72..301a288a5b 100644 --- a/packages/vkui/src/components/DateRangeInput/DateRangeInput.tsx +++ b/packages/vkui/src/components/DateRangeInput/DateRangeInput.tsx @@ -15,6 +15,7 @@ import { InputLike } from '../InputLike/InputLike'; import { InputLikeDivider } from '../InputLike/InputLikeDivider'; import { Popper } from '../Popper/Popper'; import { Text } from '../Typography/Text/Text'; +import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden'; import styles from './DateRangeInput.module.css'; import dateInputStyles from '../DateInput/DateInput.module.css'; @@ -34,11 +35,11 @@ export interface DateRangeInputProps | 'value' | 'weekStartsOn' | 'disablePickers' - | 'prevMonthAriaLabel' - | 'nextMonthAriaLabel' - | 'changeMonthAriaLabel' - | 'changeYearAriaLabel' - | 'changeDayAriaLabel' + | 'prevMonthLabel' + | 'nextMonthLabel' + | 'changeMonthLabel' + | 'changeYearLabel' + | 'changeDayLabel' | 'prevMonthIcon' | 'nextMonthIcon' >, @@ -46,14 +47,14 @@ export interface DateRangeInputProps FormFieldProps { calendarPlacement?: PlacementWithAuto; closeOnChange?: boolean; - clearFieldAriaLabel?: string; - showCalendarAriaLabel?: string; - changeStartDayAriaLabel?: string; - changeStartMonthAriaLabel?: string; - changeStartYearAriaLabel?: string; - changeEndDayAriaLabel?: string; - changeEndMonthAriaLabel?: string; - changeEndYearAriaLabel?: string; + clearFieldLabel?: string; + showCalendarLabel?: string; + changeStartDayLabel?: string; + changeStartMonthLabel?: string; + changeStartYearLabel?: string; + changeEndDayLabel?: string; + changeEndMonthLabel?: string; + changeEndYearLabel?: string; disableCalendar?: boolean; } @@ -117,19 +118,19 @@ export const DateRangeInput = ({ disabled, onClick, onFocus, - prevMonthAriaLabel, - nextMonthAriaLabel, - changeDayAriaLabel, - changeMonthAriaLabel, - changeYearAriaLabel, - changeStartDayAriaLabel = 'Изменить день начала', - changeStartMonthAriaLabel = 'Изменить месяц начала', - changeStartYearAriaLabel = 'Изменить год начала', - changeEndDayAriaLabel = 'Изменить день окончания', - changeEndMonthAriaLabel = 'Изменить месяц окончания', - changeEndYearAriaLabel = 'Изменить год окончания', - clearFieldAriaLabel = 'Очистить поле', - showCalendarAriaLabel = 'Показать календарь', + prevMonthLabel = 'Предыдущий месяц', + nextMonthLabel = 'Следующий месяц', + changeDayLabel = 'Изменить день', + changeMonthLabel = 'Изменить месяц', + changeYearLabel = 'Изменить год', + changeStartDayLabel = 'Изменить день начала', + changeStartMonthLabel = 'Изменить месяц начала', + changeStartYearLabel = 'Изменить год начала', + changeEndDayLabel = 'Изменить день окончания', + changeEndMonthLabel = 'Изменить месяц окончания', + changeEndYearLabel = 'Изменить год окончания', + clearFieldLabel = 'Очистить поле', + showCalendarLabel = 'Показать календарь', prevMonthIcon, nextMonthIcon, disableCalendar = false, @@ -236,11 +237,13 @@ export const DateRangeInput = ({ getRootRef={handleRootRef} after={ value ? ( - + + {clearFieldLabel} ) : ( - + + {showCalendarLabel} ) @@ -268,7 +271,7 @@ export const DateRangeInput = ({ index={0} onElementSelect={setFocusedElement} value={internalValue[0]} - aria-label={changeStartDayAriaLabel} + label={changeStartDayLabel} /> . . {' — '} . . {open && !disableCalendar && ( @@ -327,11 +330,11 @@ export const DateRangeInput = ({ onClose={closeCalendar} getRootRef={calendarRef} disablePickers={disablePickers} - prevMonthAriaLabel={prevMonthAriaLabel} - nextMonthAriaLabel={nextMonthAriaLabel} - changeMonthAriaLabel={changeMonthAriaLabel} - changeYearAriaLabel={changeYearAriaLabel} - changeDayAriaLabel={changeDayAriaLabel} + prevMonthLabel={prevMonthLabel} + nextMonthLabel={nextMonthLabel} + changeMonthLabel={changeMonthLabel} + changeYearLabel={changeYearLabel} + changeDayLabel={changeDayLabel} prevMonthIcon={prevMonthIcon} nextMonthIcon={nextMonthIcon} /> diff --git a/packages/vkui/src/components/InputLike/InputLike.tsx b/packages/vkui/src/components/InputLike/InputLike.tsx index 80571bcc28..06873e04b7 100644 --- a/packages/vkui/src/components/InputLike/InputLike.tsx +++ b/packages/vkui/src/components/InputLike/InputLike.tsx @@ -1,14 +1,15 @@ import * as React from 'react'; import { callMultiple } from '../../lib/callMultiple'; import { stopPropagation } from '../../lib/utils'; -import { HTMLAttributesWithRootRef } from '../../types'; -import { RootComponent } from '../RootComponent/RootComponent'; +import { RootComponent, type RootComponentProps } from '../RootComponent/RootComponent'; +import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden'; import styles from './InputLike.module.css'; -export interface InputLikeProps extends HTMLAttributesWithRootRef { +export interface InputLikeProps extends RootComponentProps { length: number; index: number; value?: string; + label?: string; onElementSelect?(index: number): void; } @@ -33,7 +34,8 @@ export const InputLike = ({ onElementSelect, onClick, onFocus, - ...props + label, + ...restProps }: InputLikeProps) => { const handleElementSelect = React.useCallback( (event: React.MouseEvent) => { @@ -50,8 +52,9 @@ export const InputLike = ({ tabIndex={0} onClick={callMultiple(onClick, handleElementSelect)} onFocus={callMultiple(stopPropagation, onFocus)} - {...props} + {...restProps} > + {label && {label}} {value?.slice(0, length - 1)} {value?.slice(length - 1) && ( diff --git a/packages/vkui/src/components/ModalCardBase/ModalCardBase.tsx b/packages/vkui/src/components/ModalCardBase/ModalCardBase.tsx index a7994ec898..e678b1993f 100644 --- a/packages/vkui/src/components/ModalCardBase/ModalCardBase.tsx +++ b/packages/vkui/src/components/ModalCardBase/ModalCardBase.tsx @@ -49,7 +49,7 @@ export interface ModalCardBaseProps extends HTMLAttributesWithRootRef{actions}
} + > + {dismissLabel} + ); diff --git a/packages/vkui/src/components/ModalCardBase/ModalCardBaseCloseButton.tsx b/packages/vkui/src/components/ModalCardBase/ModalCardBaseCloseButton.tsx index f06072f504..bcc8a4db05 100644 --- a/packages/vkui/src/components/ModalCardBase/ModalCardBaseCloseButton.tsx +++ b/packages/vkui/src/components/ModalCardBase/ModalCardBaseCloseButton.tsx @@ -3,18 +3,18 @@ import { Icon20Cancel, Icon24Dismiss } from '@vkontakte/icons'; import { useAdaptivityWithJSMediaQueries } from '../../hooks/useAdaptivityWithJSMediaQueries'; import { usePlatform } from '../../hooks/usePlatform'; import { ModalDismissButton } from '../ModalDismissButton/ModalDismissButton'; -import { Tappable } from '../Tappable/Tappable'; +import { Tappable, TappableProps } from '../Tappable/Tappable'; +import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden'; import styles from './ModalCardBase.module.css'; -interface ModalCardBaseCloseButtonProps { +interface ModalCardBaseCloseButtonProps extends Omit { onClose?: VoidFunction; - dismissLabel?: string; testId?: string; mode?: 'inside' | 'outside'; } export function ModalCardBaseCloseButton({ - dismissLabel, + children = 'Закрыть', testId, mode, onClose, @@ -23,19 +23,23 @@ export function ModalCardBaseCloseButton({ const { isDesktop } = useAdaptivityWithJSMediaQueries(); if (isDesktop && mode === 'outside') { - return ; + return ( + + {children} + + ); } if (mode === 'inside' || (platform === 'ios' && !isDesktop)) { return ( + {children} {platform === 'ios' ? : } ); diff --git a/packages/vkui/src/components/ModalCardBase/Readme.md b/packages/vkui/src/components/ModalCardBase/Readme.md index a7519031c8..7d3bd44a84 100644 --- a/packages/vkui/src/components/ModalCardBase/Readme.md +++ b/packages/vkui/src/components/ModalCardBase/Readme.md @@ -44,11 +44,16 @@ Согласно нашим дизайн-гайдам, `dismissButtonMode=outside` отображается только для `compact`-режима (десктопная и планшетные версии). Для `iOS` всегда будет применяться `dismissButtonMode=inside` в `regular`-режиме (мобильная версия). +## Цифровая доступность (a11y) + +Чтобы кнопка для закрытия была доступной для ассистивных технологий, мы передаем в нее скрытый визуально текст, который сможет прочитать скринридер. Чтобы заменить текст, передайте его в `dismissLabel`. + ```jsx { "props": { "layout": false, "iframe": false } }
; +export type ModalDismissButtonProps = Omit; /** * @see https://vkcom.github.io/VKUI/#/ModalDismissButton */ export const ModalDismissButton = ({ - 'aria-label': ariaLabel = 'Закрыть', + children = 'Закрыть', className, ...restProps }: ModalDismissButtonProps) => { @@ -19,10 +19,10 @@ export const ModalDismissButton = ({ + {children && {children}} ); diff --git a/packages/vkui/src/components/ModalDismissButton/Readme.md b/packages/vkui/src/components/ModalDismissButton/Readme.md index 394aa4f0a9..1b279d6d15 100644 --- a/packages/vkui/src/components/ModalDismissButton/Readme.md +++ b/packages/vkui/src/components/ModalDismissButton/Readme.md @@ -1,6 +1,10 @@ Кнопка для закрытия модальных окон на широком экране. Для правильной отрисовки нужно расположить в контейнере с `position: "relative"` и отображать при достаточной ширине экрана (от `ViewWidth.SMALL_TABLET`) +## Цифровая доступность (a11y) + +Чтобы кнопка была доступной для ассистивных технологий, мы передаем в нее скрытый визуально текст, который сможет прочитать скринридер. Сейчас по умолчанию это — "Закрыть". Чтобы заменить текст, передайте его в `children`. + ```jsx { "props": { "layout": false, "adaptivity": true } } const CustomPopout = ({ onClose }) => { const { sizeX } = useAdaptivityConditionalRender(); @@ -17,7 +21,9 @@ const CustomPopout = ({ onClose }) => {

Кастомное модальное окно

{sizeX.regular && ( - + + Закрыть кастомное модальное окно + )}
diff --git a/packages/vkui/src/components/Pagination/Pagination.tsx b/packages/vkui/src/components/Pagination/Pagination.tsx index 3554558593..a6f27885a6 100644 --- a/packages/vkui/src/components/Pagination/Pagination.tsx +++ b/packages/vkui/src/components/Pagination/Pagination.tsx @@ -1,12 +1,13 @@ import * as React from 'react'; import { Icon24ChevronCompactLeft, Icon24ChevronCompactRight } from '@vkontakte/icons'; import { PaginationPageType, usePagination } from '../../hooks/usePagination'; -import type { HTMLAttributesWithRootRef } from '../../types'; +import type { HasComponent, HTMLAttributesWithRootRef } from '../../types'; import { Button } from '../Button/Button'; import { RootComponent } from '../RootComponent/RootComponent'; +import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden'; import { PaginationPageButton } from './PaginationPage/PaginationPageButton'; import { PaginationPageEllipsis } from './PaginationPage/PaginationPageEllipsis'; -import { getPageAriaLabelDefault } from './utils'; +import { getPageLabelDefault } from './utils'; import styles from './Pagination.module.css'; export interface PaginationProps extends Omit, 'onChange'> { @@ -31,20 +32,26 @@ export interface PaginationProps extends Omit { @@ -107,7 +116,7 @@ export const Pagination = ({ return (
  • + + {navigationLabel}
    • @@ -145,11 +154,15 @@ export const Pagination = ({
    • diff --git a/packages/vkui/src/components/Pagination/PaginationPage/PaginationPageButton.tsx b/packages/vkui/src/components/Pagination/PaginationPage/PaginationPageButton.tsx index bc2ac24f7e..2f9759aaa1 100644 --- a/packages/vkui/src/components/Pagination/PaginationPage/PaginationPageButton.tsx +++ b/packages/vkui/src/components/Pagination/PaginationPage/PaginationPageButton.tsx @@ -3,25 +3,23 @@ import { classNames } from '@vkontakte/vkjs'; import type { HasRootRef } from '../../../types'; import { Tappable } from '../../Tappable/Tappable'; import { Text } from '../../Typography/Text/Text'; -import { getPageAriaLabelDefault } from '../utils'; +import { VisuallyHidden } from '../../VisuallyHidden/VisuallyHidden'; +import { PaginationProps } from '../Pagination'; +import { getPageLabelDefault } from '../utils'; import { usePaginationPageClassNames } from './usePaginationPageClasses'; import styles from './PaginationPage.module.css'; export interface PaginationPageButtonProps extends React.ButtonHTMLAttributes, - HasRootRef { + HasRootRef, + Pick { isCurrent?: boolean; - /** - * Функция для переопределения и/или локализации `aria-label` атрибута. - * По умолчанию используется текст на "ru_RU". - */ - getPageAriaLabel?(page: number, isCurrent: boolean): string; children: number; } export const PaginationPageButton = ({ isCurrent = false, - getPageAriaLabel = getPageAriaLabelDefault, + getPageLabel = getPageLabelDefault, children, className, disabled, @@ -39,11 +37,13 @@ export const PaginationPageButton = ({ focusVisibleMode="outside" data-page={children} aria-current={isCurrent ? true : undefined} - aria-label={getPageAriaLabel(children, isCurrent)} disabled={disabled} {...restProps} > - {children} + + {getPageLabel(isCurrent)} + {children} + ); }; diff --git a/packages/vkui/src/components/Pagination/utils.ts b/packages/vkui/src/components/Pagination/utils.ts index 13c7d26e11..f453665eaa 100644 --- a/packages/vkui/src/components/Pagination/utils.ts +++ b/packages/vkui/src/components/Pagination/utils.ts @@ -1,3 +1,3 @@ -export function getPageAriaLabelDefault(page: number, isCurrent: boolean): string { - return isCurrent ? `${page} страница` : `Перейти на ${page} страницу`; +export function getPageLabelDefault(isCurrent: boolean): string { + return isCurrent ? `Cтраница` : `Перейти на страницу`; } diff --git a/packages/vkui/src/components/PanelHeader/PanelHeader.stories.tsx b/packages/vkui/src/components/PanelHeader/PanelHeader.stories.tsx index 247c2634f8..b9aa406335 100644 --- a/packages/vkui/src/components/PanelHeader/PanelHeader.stories.tsx +++ b/packages/vkui/src/components/PanelHeader/PanelHeader.stories.tsx @@ -23,6 +23,7 @@ import { Search } from '../Search/Search'; import { Tabs } from '../Tabs/Tabs'; import { TabsItem } from '../TabsItem/TabsItem'; import { View } from '../View/View'; +import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden'; import { PanelHeader, PanelHeaderProps } from './PanelHeader'; const story: Meta = { @@ -59,13 +60,14 @@ export const PanelHeaderWithCounter: Story = { before={} after={ + + Новых: 21 } > + Изображения - 3 + + Новых: 3 } > + Настройки + 2 } > + Уведомления { } after={ Обновлений: @@ -54,6 +53,7 @@ const Example = () => { } > + Изображения { after={ Новых: 3 } > + Настройки 2 @@ -97,6 +96,7 @@ const Example = () => { IconCompact={Icon24NotificationOutline} IconRegular={Icon28Notifications} /> + Уведомления } diff --git a/packages/vkui/src/components/PanelHeaderBack/PanelHeaderBack.tsx b/packages/vkui/src/components/PanelHeaderBack/PanelHeaderBack.tsx index ae8710fa46..d27ec11735 100644 --- a/packages/vkui/src/components/PanelHeaderBack/PanelHeaderBack.tsx +++ b/packages/vkui/src/components/PanelHeaderBack/PanelHeaderBack.tsx @@ -12,11 +12,12 @@ import { usePlatform } from '../../hooks/usePlatform'; import { PlatformType } from '../../lib/platform'; import { AdaptiveIconRenderer } from '../AdaptiveIconRenderer/AdaptiveIconRenderer'; import { PanelHeaderButton, PanelHeaderButtonProps } from '../PanelHeaderButton/PanelHeaderButton'; +import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden'; import styles from '../PanelHeaderButton/PanelHeaderButton.module.css'; -export type PanelHeaderBackProps = PanelHeaderButtonProps & { - 'aria-label'?: string; -}; +export interface PanelHeaderBackProps extends Omit { + children?: string; +} const getBackIcon = (platform: PlatformType) => { switch (platform) { @@ -44,13 +45,13 @@ const getBackIcon = (platform: PlatformType) => { */ export const PanelHeaderBack = ({ label, - 'aria-label': ariaLabel = 'Назад', className, + children = 'Назад', ...restProps }: PanelHeaderButtonProps) => { const platform = usePlatform(); const { sizeX = 'none' } = useAdaptivity(); - // так-же label нужно скрывать при platform === 'ios' && sizeX === regular + // также label нужно скрывать при platform === 'ios' && sizeX === regular // https://github.com/VKCOM/VKUI/blob/master/src/components/PanelHeaderButton/PanelHeaderButton.css#L104 const showLabel = platform === 'vkcom' || platform === 'ios'; @@ -65,8 +66,8 @@ export const PanelHeaderBack = ({ className, )} label={showLabel && label} - aria-label={ariaLabel} > + {children && {children}} {getBackIcon(platform)} ); diff --git a/packages/vkui/src/components/PanelHeaderButton/PanelHeaderButton.tsx b/packages/vkui/src/components/PanelHeaderButton/PanelHeaderButton.tsx index cfb3a9ef85..a3fa9cec10 100644 --- a/packages/vkui/src/components/PanelHeaderButton/PanelHeaderButton.tsx +++ b/packages/vkui/src/components/PanelHeaderButton/PanelHeaderButton.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import { classNames, isPrimitiveReactNode } from '@vkontakte/vkjs'; import { usePlatform } from '../../hooks/usePlatform'; -import { getTitleFromChildren } from '../../lib/utils'; -import { warnOnce } from '../../lib/warnOnce'; +import { hasAccessibleName } from '../../lib/accessibility'; +import { COMMON_WARNINGS, warnOnce } from '../../lib/warnOnce'; import { Tappable, TappableProps } from '../Tappable/Tappable'; import { Text } from '../Typography/Text/Text'; import { Title } from '../Typography/Title/Title'; @@ -71,18 +71,14 @@ export const PanelHeaderButton = ({ } if (process.env.NODE_ENV === 'development') { - const hasAccessibleName = Boolean( - getTitleFromChildren(children) || - getTitleFromChildren(label) || - restProps['aria-label'] || - restProps['aria-labelledby'], - ); + /* istanbul ignore next: проверка в dev mode, тест на hasAccessibleName() есть в lib/accessibility.test.tsx */ + const isAccessible = hasAccessibleName({ + children: [children, label], + ...restProps, + }); - if (!hasAccessibleName) { - warn( - 'a11y: У кнопки нет названия, которое может прочитать скринридер, и она недоступна для части пользователей. Замените содержимое на текст или добавьте описание действия с помощью пропа aria-label.', - 'error', - ); + if (!isAccessible) { + warn(COMMON_WARNINGS.a11y[restProps.href ? 'link-name' : 'button-name'], 'error'); } } diff --git a/packages/vkui/src/components/PanelHeaderClose/PanelHeaderClose.tsx b/packages/vkui/src/components/PanelHeaderClose/PanelHeaderClose.tsx index 4ff25c2b89..0268a99ec5 100644 --- a/packages/vkui/src/components/PanelHeaderClose/PanelHeaderClose.tsx +++ b/packages/vkui/src/components/PanelHeaderClose/PanelHeaderClose.tsx @@ -1,21 +1,28 @@ import * as React from 'react'; import { Icon24CancelOutline, Icon28CancelOutline } from '@vkontakte/icons'; import { usePlatform } from '../../hooks/usePlatform'; -import { getTitleFromChildren } from '../../lib/utils'; import { AdaptiveIconRenderer } from '../AdaptiveIconRenderer/AdaptiveIconRenderer'; import { PanelHeaderButton, PanelHeaderButtonProps } from '../PanelHeaderButton/PanelHeaderButton'; +import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden'; /** * @see https://vkcom.github.io/VKUI/#/PanelHeaderButton */ export const PanelHeaderClose = ({ children = 'Отмена', ...restProps }: PanelHeaderButtonProps) => { const platform = usePlatform(); + return ( - + {platform === 'ios' ? ( children ) : ( - + <> + {children} + + )} ); diff --git a/packages/vkui/src/components/PanelHeaderEdit/PanelHeaderEdit.tsx b/packages/vkui/src/components/PanelHeaderEdit/PanelHeaderEdit.tsx index 4fa59d1919..eeb0c50445 100644 --- a/packages/vkui/src/components/PanelHeaderEdit/PanelHeaderEdit.tsx +++ b/packages/vkui/src/components/PanelHeaderEdit/PanelHeaderEdit.tsx @@ -8,6 +8,7 @@ import { import { usePlatform } from '../../hooks/usePlatform'; import { AdaptiveIconRenderer } from '../AdaptiveIconRenderer/AdaptiveIconRenderer'; import { PanelHeaderButton, PanelHeaderButtonProps } from '../PanelHeaderButton/PanelHeaderButton'; +import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden'; export interface PanelHeaderEditProps extends PanelHeaderButtonProps { /** @@ -15,11 +16,11 @@ export interface PanelHeaderEditProps extends PanelHeaderButtonProps { */ isActive?: boolean; /** - * iOS only. Текст кнопки, когда режим редактирования не активен + * Текст кнопки, когда режим редактирования не активен. Визуально скрыт везде, кроме iOS */ editLabel?: string; /** - * iOS only. Текст кнопки при активном режиме редактирования для выхода из него + * Текст кнопки при активном режиме редактирования для выхода из него. Визуально скрыт везде, кроме iOS */ doneLabel?: string; } @@ -33,18 +34,21 @@ export const PanelHeaderEdit = ({ doneLabel = 'Готово', ...restProps }: PanelHeaderEditProps) => { - const iOSText = isActive ? doneLabel : editLabel; const platform = usePlatform(); + const label = isActive ? doneLabel : editLabel; return ( - + {platform === 'ios' ? ( - iOSText + label ) : ( - + <> + {label} + + )} ); diff --git a/packages/vkui/src/components/PanelHeaderSubmit/PanelHeaderSubmit.tsx b/packages/vkui/src/components/PanelHeaderSubmit/PanelHeaderSubmit.tsx index 6d000692d2..5d404a268c 100644 --- a/packages/vkui/src/components/PanelHeaderSubmit/PanelHeaderSubmit.tsx +++ b/packages/vkui/src/components/PanelHeaderSubmit/PanelHeaderSubmit.tsx @@ -1,9 +1,9 @@ import * as React from 'react'; import { Icon24DoneOutline, Icon28DoneOutline } from '@vkontakte/icons'; import { usePlatform } from '../../hooks/usePlatform'; -import { getTitleFromChildren } from '../../lib/utils'; import { AdaptiveIconRenderer } from '../AdaptiveIconRenderer/AdaptiveIconRenderer'; import { PanelHeaderButton, PanelHeaderButtonProps } from '../PanelHeaderButton/PanelHeaderButton'; +import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden'; /** * @see https://vkcom.github.io/VKUI/#/PanelHeaderButton @@ -15,11 +15,14 @@ export const PanelHeaderSubmit = ({ const platform = usePlatform(); return ( - + {platform === 'ios' ? ( children ) : ( - + <> + {children} + + )} ); diff --git a/packages/vkui/src/components/Removable/Removable.tsx b/packages/vkui/src/components/Removable/Removable.tsx index f6f19672bc..11b75e6a3f 100644 --- a/packages/vkui/src/components/Removable/Removable.tsx +++ b/packages/vkui/src/components/Removable/Removable.tsx @@ -3,8 +3,8 @@ import { Icon24Cancel } from '@vkontakte/icons'; import { classNames, noop } from '@vkontakte/vkjs'; import { useGlobalEventListener } from '../../hooks/useGlobalEventListener'; import { usePlatform } from '../../hooks/usePlatform'; +import { getTextFromChildren } from '../../lib/children'; import { useDOM } from '../../lib/dom'; -import { getTitleFromChildren } from '../../lib/utils'; import { HTMLAttributesWithRootRef } from '../../types'; import { IconButton } from '../IconButton/IconButton'; import { RootComponent } from '../RootComponent/RootComponent'; @@ -170,7 +170,7 @@ export const Removable = ({ onRemove(e); }; - const removePlaceholderString: string = getTitleFromChildren(removePlaceholder); + const removePlaceholderString: string = getTextFromChildren(removePlaceholder); return ( { - baselineComponent((props) => ( - - )); + baselineComponent((props) => ); it('should have HTML style attribute for offsetY prop', () => { const offsetY = 10; diff --git a/packages/vkui/src/components/ScrollArrow/ScrollArrow.tsx b/packages/vkui/src/components/ScrollArrow/ScrollArrow.tsx index 7246984165..e0f3bc522f 100644 --- a/packages/vkui/src/components/ScrollArrow/ScrollArrow.tsx +++ b/packages/vkui/src/components/ScrollArrow/ScrollArrow.tsx @@ -3,6 +3,7 @@ import { Icon16Chevron, Icon24Chevron } from '@vkontakte/icons'; import { classNames } from '@vkontakte/vkjs'; import { HasRootRef } from '../../types'; import { RootComponent } from '../RootComponent/RootComponent'; +import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden'; import styles from './ScrollArrow.module.css'; const stylesSize = { @@ -17,6 +18,13 @@ const stylesDirection = { left: styles['ScrollArrow--direction-left'], }; +const labelDirection = { + up: 'Назад', + right: 'Вперед', + down: 'Вперед', + left: 'Назад', +}; + const ArrowIcon = ({ size }: Pick) => { let Icon = Icon24Chevron; if (size === 'm') { @@ -41,10 +49,11 @@ export interface ScrollArrowProps * Смещает иконку кнопки навигации по вертикали. */ offsetY?: number | string; + label?: string; } /** - * Компонент стрелки из HorizontalScroll + * Компонент стрелки. Используется в [HorizontalScroll](#/HorizontalScroll) и [Gallery](#/Gallery). * * @since 5.4.0 * @see https://vkcom.github.io/VKUI/#/ScrollArrow @@ -53,9 +62,12 @@ export const ScrollArrow = ({ size = 'l', offsetY, direction, + label: labelProp, children = , ...restProps }: ScrollArrowProps) => { + const label = labelProp ?? labelDirection[direction]; + return ( + {label && {label}} {children} diff --git a/packages/vkui/src/components/Search/Readme.md b/packages/vkui/src/components/Search/Readme.md index db8369121a..55b54be795 100644 --- a/packages/vkui/src/components/Search/Readme.md +++ b/packages/vkui/src/components/Search/Readme.md @@ -46,7 +46,8 @@ const SimpleSearch = ({ goHeaderSearch }) => { + + Добавить } @@ -131,14 +132,22 @@ const SearchExample = () => { + + Отмена ) } after={ - - {platform === 'ios' ? 'Готово' : } + + {platform === 'ios' ? ( + 'Готово' + ) : ( + <> + Готово + + + )} } > diff --git a/packages/vkui/src/components/Search/Search.tsx b/packages/vkui/src/components/Search/Search.tsx index 5946b4bf59..06362703be 100644 --- a/packages/vkui/src/components/Search/Search.tsx +++ b/packages/vkui/src/components/Search/Search.tsx @@ -13,6 +13,7 @@ import { Button } from '../Button/Button'; import { IconButton } from '../IconButton/IconButton'; import { TouchEvent } from '../Touch/Touch'; import { Headline } from '../Typography/Headline/Headline'; +import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden'; import styles from './Search.module.css'; export interface SearchProps @@ -27,8 +28,8 @@ export interface SearchProps icon?: React.ReactNode; onIconClick?(e: VKUITouchEvent): void; defaultValue?: string; - iconAriaLabel?: string; - clearAriaLabel?: string; + iconLabel?: string; + clearLabel?: string; /** * Удаляет отступы у компонента */ @@ -60,8 +61,8 @@ export const Search = ({ autoComplete = 'off', onChange: onChangeProp, value: valueProp, - iconAriaLabel, - clearAriaLabel = 'Очистить', + iconLabel, + clearLabel = 'Очистить', noPadding, getRootRef, findButtonText = 'Найти', @@ -173,8 +174,8 @@ export const Search = ({ className={styles['Search__icon']} onFocus={setFocusedTrue} onBlur={setFocusedFalse} - label={iconAriaLabel} > + {iconLabel} {icon} )} @@ -183,9 +184,9 @@ export const Search = ({ onStart={onIconCancelClickStart} onClick={onCancel} className={styles['Search__icon']} - label={clearAriaLabel} tabIndex={value ? undefined : -1} > + {clearLabel} {platform === 'ios' ? : } {adaptiveSizeY.compact && onFindButtonClick && ( diff --git a/packages/vkui/src/components/TabbarItem/Readme.md b/packages/vkui/src/components/TabbarItem/Readme.md index e0503af62e..80667bdf00 100644 --- a/packages/vkui/src/components/TabbarItem/Readme.md +++ b/packages/vkui/src/components/TabbarItem/Readme.md @@ -1,5 +1,14 @@ Элемент [Tabbar](#!/Tabbar). В качестве `children` рекомендуется использовать [иконку](https://vkcom.github.io/icons) 28 размера. +## Цифровая доступность (a11y) + +Чтобы `TabbarItem` был доступным для ассистивных технологий, у него должен быть текст, который сможет прочитать скринридер. Если вы не передаете `text`, то передайте одновременно с иконкой текст, обернутый в компонент [VisuallyHidden](#!/VisuallyHidden). + +Как еще можно это сделать: + +- Передать `aria-label` или `title`. +- Создать отдельный элемент с текстом и передать его `id` в `aria-labelledby` кнопки. + ```jsx { "props": { "layout": false, "iframe": false } } const [simple, setSimple] = useState('one'); const [text, setText] = useState('one'); @@ -14,10 +23,12 @@ const [indicator, setIndicator] = useState('one'); >
      - setSimple('one')} aria-label="Новости"> + setSimple('one')}> + Новости - setSimple('two')} aria-label="Профиль"> + setSimple('two')}> + Профиль diff --git a/packages/vkui/src/components/VisuallyHidden/VisuallyHidden.tsx b/packages/vkui/src/components/VisuallyHidden/VisuallyHidden.tsx index e106f50fcf..16e168897d 100644 --- a/packages/vkui/src/components/VisuallyHidden/VisuallyHidden.tsx +++ b/packages/vkui/src/components/VisuallyHidden/VisuallyHidden.tsx @@ -1,12 +1,8 @@ import * as React from 'react'; -import { HasComponent, HasRootRef } from '../../types'; -import { RootComponent } from '../RootComponent/RootComponent'; +import { RootComponent, type RootComponentProps } from '../RootComponent/RootComponent'; import styles from './VisuallyHidden.module.css'; -interface VisuallyHiddenProps - extends React.AllHTMLAttributes, - HasRootRef, - HasComponent {} +export type VisuallyHiddenProps = RootComponentProps; /** * Компонент-обертка. Позволяет скрыть контент визуально, но оставить его @@ -15,6 +11,9 @@ interface VisuallyHiddenProps * @since v5.4.0 * @see https://vkcom.github.io/VKUI/#/VisuallyHidden */ -export const VisuallyHidden = ({ Component = 'span', ...restProps }: VisuallyHiddenProps) => ( +export const VisuallyHidden = ({ + Component = 'span', + ...restProps +}: VisuallyHiddenProps) => ( ); diff --git a/packages/vkui/src/components/WriteBar/Readme.md b/packages/vkui/src/components/WriteBar/Readme.md index e53f791275..c5e12600e1 100644 --- a/packages/vkui/src/components/WriteBar/Readme.md +++ b/packages/vkui/src/components/WriteBar/Readme.md @@ -72,15 +72,11 @@ const WriteBarExample = (props) => { before={} after={ <> - {SmileOutlineIcon} + {SmileOutlineIcon} - - {CameraOutlineIcon} - + {CameraOutlineIcon} - - {VoiceOutlineIcon} - + {VoiceOutlineIcon} } placeholder="Сообщение" @@ -95,22 +91,20 @@ const WriteBarExample = (props) => { inlineAfter={ <> {text2.length === 0 && ( - - {KeyboardBotsOutlineIcon} - + {KeyboardBotsOutlineIcon} )} {text2.length > 0 && ( - {SmileOutlineIcon} + {SmileOutlineIcon} )} } after={ <> {text2.length === 0 && ( - {SmileOutlineIcon} + {SmileOutlineIcon} )} {text2.length === 0 && ( - + {VoiceOutlineIcon} )} @@ -128,13 +122,13 @@ const WriteBarExample = (props) => { before={} inlineAfter={ text3.length > 0 && ( - {SmileOutlineIcon} + {SmileOutlineIcon} ) } after={ <> {text3.length === 0 && ( - {SmileOutlineIcon} + {SmileOutlineIcon} )} @@ -150,13 +144,13 @@ const WriteBarExample = (props) => { before={} inlineAfter={ text4.length > 0 && ( - {SmileOutlineIcon} + {SmileOutlineIcon} ) } after={ <> {text4.length === 0 && ( - {SmileOutlineIcon} + {SmileOutlineIcon} )} @@ -188,16 +182,16 @@ const WriteBarExample = (props) => { } inlineAfter={ text.length > 0 && ( - {SmileOutlineIcon} + {SmileOutlineIcon} ) } after={ <> {text.length === 0 && ( - {SmileOutlineIcon} + {SmileOutlineIcon} )} {text.length === 0 && ( - + {VoiceOutlineIcon} )} diff --git a/packages/vkui/src/components/WriteBar/WriteBar.e2e-playground.tsx b/packages/vkui/src/components/WriteBar/WriteBar.e2e-playground.tsx index 9ed632bffb..655e29017b 100644 --- a/packages/vkui/src/components/WriteBar/WriteBar.e2e-playground.tsx +++ b/packages/vkui/src/components/WriteBar/WriteBar.e2e-playground.tsx @@ -37,18 +37,16 @@ const WriteBarTestComponent = ({ value, ...restProps }: WriteBarProps) => { before={} inlineAfter={ stringValue.length > 0 && ( - {SmileOutlineIcon} + {SmileOutlineIcon} ) } after={ <> {stringValue.length === 0 && ( - {SmileOutlineIcon} + {SmileOutlineIcon} )} {stringValue.length === 0 && ( - - {VoiceOutlineIcon} - + {VoiceOutlineIcon} )} {stringValue.length > 0 && } @@ -77,7 +75,7 @@ export const WriteBarPlayground = (props: ComponentPlaygroundProps) => { }; const WriteBarIosSmileIcon = ( - + ); diff --git a/packages/vkui/src/components/WriteBar/WriteBar.stories.tsx b/packages/vkui/src/components/WriteBar/WriteBar.stories.tsx index 2c75038899..b39daaf676 100644 --- a/packages/vkui/src/components/WriteBar/WriteBar.stories.tsx +++ b/packages/vkui/src/components/WriteBar/WriteBar.stories.tsx @@ -20,7 +20,7 @@ export const Playground: Story = { before: , placeholder: 'Сообщение', inlineAfter: ( - + ), diff --git a/packages/vkui/src/components/WriteBarIcon/Readme.md b/packages/vkui/src/components/WriteBarIcon/Readme.md index 78a8a0ebc5..b4f4f394dd 100644 --- a/packages/vkui/src/components/WriteBarIcon/Readme.md +++ b/packages/vkui/src/components/WriteBarIcon/Readme.md @@ -1,11 +1,39 @@ -Компонент для отрисовки кнопок-иконок в `WriteBar`. +Компонент для отрисовки кнопок-иконок внутри [WriteBar](#!/WriteBar). Надстройка над `