@vkontakte/vkui 7.1.2 → 7.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Alert/Alert.js +5 -5
- package/dist/components/Alert/Alert.js.map +1 -1
- package/dist/components/CarouselBase/CarouselBase.d.ts.map +1 -1
- package/dist/components/CarouselBase/CarouselBase.js +1 -4
- package/dist/components/CarouselBase/CarouselBase.js.map +1 -1
- package/dist/components/FormItem/FormItem.d.ts.map +1 -1
- package/dist/components/FormItem/FormItem.js +1 -0
- package/dist/components/FormItem/FormItem.js.map +1 -1
- package/dist/components/HorizontalScroll/HorizontalScroll.d.ts +1 -1
- package/dist/components/HorizontalScroll/HorizontalScroll.d.ts.map +1 -1
- package/dist/components/HorizontalScroll/HorizontalScroll.js +17 -18
- package/dist/components/HorizontalScroll/HorizontalScroll.js.map +1 -1
- package/dist/components/ModalCard/ModalCardInternal.d.ts +1 -1
- package/dist/components/ModalCard/ModalCardInternal.d.ts.map +1 -1
- package/dist/components/ModalCard/ModalCardInternal.js +4 -3
- package/dist/components/ModalCard/ModalCardInternal.js.map +1 -1
- package/dist/components/ModalCard/types.d.ts +7 -0
- package/dist/components/ModalCard/types.d.ts.map +1 -1
- package/dist/components/ModalCard/types.js.map +1 -1
- package/dist/components/ModalPage/ModalPageInternal.d.ts +1 -1
- package/dist/components/ModalPage/ModalPageInternal.d.ts.map +1 -1
- package/dist/components/ModalPage/ModalPageInternal.js +4 -3
- package/dist/components/ModalPage/ModalPageInternal.js.map +1 -1
- package/dist/components/ModalPage/types.d.ts +7 -0
- package/dist/components/ModalPage/types.d.ts.map +1 -1
- package/dist/components/ModalPage/types.js.map +1 -1
- package/dist/components/OnboardingTooltip/OnboardingTooltip.d.ts +7 -2
- package/dist/components/OnboardingTooltip/OnboardingTooltip.d.ts.map +1 -1
- package/dist/components/OnboardingTooltip/OnboardingTooltip.js +32 -13
- package/dist/components/OnboardingTooltip/OnboardingTooltip.js.map +1 -1
- package/dist/components/Pagination/Pagination.d.ts +6 -0
- package/dist/components/Pagination/Pagination.d.ts.map +1 -1
- package/dist/components/Pagination/Pagination.js +5 -3
- package/dist/components/Pagination/Pagination.js.map +1 -1
- package/dist/components/Pagination/PaginationPage/PaginationPageButton.d.ts.map +1 -1
- package/dist/components/Pagination/PaginationPage/PaginationPageButton.js +4 -4
- package/dist/components/Pagination/PaginationPage/PaginationPageButton.js.map +1 -1
- package/dist/components/Removable/Removable.d.ts +5 -1
- package/dist/components/Removable/Removable.d.ts.map +1 -1
- package/dist/components/Removable/Removable.js +4 -3
- package/dist/components/Removable/Removable.js.map +1 -1
- package/dist/components/TabbarItem/TabbarItem.d.ts +1 -1
- package/dist/components/TabbarItem/TabbarItem.d.ts.map +1 -1
- package/dist/components/TabbarItem/TabbarItem.js +16 -4
- package/dist/components/TabbarItem/TabbarItem.js.map +1 -1
- package/dist/components/TooltipBase/TooltipBase.d.ts +6 -1
- package/dist/components/TooltipBase/TooltipBase.d.ts.map +1 -1
- package/dist/components/TooltipBase/TooltipBase.js +3 -1
- package/dist/components/TooltipBase/TooltipBase.js.map +1 -1
- package/dist/components.css +1 -1
- package/dist/components.css.map +1 -1
- package/dist/cssm/components/Alert/Alert.js +5 -5
- package/dist/cssm/components/Alert/Alert.js.map +1 -1
- package/dist/cssm/components/CarouselBase/CarouselBase.js +1 -4
- package/dist/cssm/components/CarouselBase/CarouselBase.js.map +1 -1
- package/dist/cssm/components/FormItem/FormItem.js +1 -0
- package/dist/cssm/components/FormItem/FormItem.js.map +1 -1
- package/dist/cssm/components/HorizontalScroll/HorizontalCellShowMore/HorizontalCellShowMore.module.css +1 -0
- package/dist/cssm/components/HorizontalScroll/HorizontalScroll.js +18 -14
- package/dist/cssm/components/HorizontalScroll/HorizontalScroll.js.map +1 -1
- package/dist/cssm/components/IconButton/IconButton.module.css +6 -0
- package/dist/cssm/components/ModalCard/ModalCardInternal.js +2 -2
- package/dist/cssm/components/ModalCard/ModalCardInternal.js.map +1 -1
- package/dist/cssm/components/ModalCard/types.js.map +1 -1
- package/dist/cssm/components/ModalPage/ModalPageInternal.js +2 -2
- package/dist/cssm/components/ModalPage/ModalPageInternal.js.map +1 -1
- package/dist/cssm/components/ModalPage/types.js.map +1 -1
- package/dist/cssm/components/OnboardingTooltip/OnboardingTooltip.js +21 -7
- package/dist/cssm/components/OnboardingTooltip/OnboardingTooltip.js.map +1 -1
- package/dist/cssm/components/OnboardingTooltip/OnboardingTooltip.module.css +15 -0
- package/dist/cssm/components/Pagination/Pagination.js +4 -2
- package/dist/cssm/components/Pagination/Pagination.js.map +1 -1
- package/dist/cssm/components/Pagination/PaginationPage/PaginationPageButton.js +4 -4
- package/dist/cssm/components/Pagination/PaginationPage/PaginationPageButton.js.map +1 -1
- package/dist/cssm/components/PanelHeaderButton/PanelHeaderButton.module.css +6 -0
- package/dist/cssm/components/Removable/Removable.js +2 -2
- package/dist/cssm/components/Removable/Removable.js.map +1 -1
- package/dist/cssm/components/Removable/Removable.module.css +3 -0
- package/dist/cssm/components/Search/Search.module.css +1 -0
- package/dist/cssm/components/SimpleCell/SimpleCell.module.css +2 -0
- package/dist/cssm/components/SubnavigationButton/SubnavigationButton.module.css +1 -0
- package/dist/cssm/components/TabbarItem/TabbarItem.js +13 -3
- package/dist/cssm/components/TabbarItem/TabbarItem.js.map +1 -1
- package/dist/cssm/components/TooltipBase/TooltipBase.js +2 -1
- package/dist/cssm/components/TooltipBase/TooltipBase.js.map +1 -1
- package/dist/cssm/components/TooltipBase/TooltipBase.module.css +1 -0
- package/dist/cssm/hooks/useFocusTrap.js +1 -1
- package/dist/cssm/hooks/useFocusTrap.js.map +1 -1
- package/dist/cssm/types.js.map +1 -1
- package/dist/hooks/useFocusTrap.js +1 -1
- package/dist/hooks/useFocusTrap.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vkui.css +1 -1
- package/dist/vkui.css.map +1 -1
- package/package.json +1 -1
- package/src/components/Alert/Alert.tsx +5 -5
- package/src/components/CarouselBase/CarouselBase.tsx +1 -6
- package/src/components/FormItem/FormItem.tsx +1 -0
- package/src/components/HorizontalScroll/HorizontalCellShowMore/HorizontalCellShowMore.module.css +1 -0
- package/src/components/HorizontalScroll/HorizontalScroll.tsx +21 -15
- package/src/components/IconButton/IconButton.module.css +5 -0
- package/src/components/ModalCard/ModalCardInternal.tsx +5 -1
- package/src/components/ModalCard/types.ts +7 -0
- package/src/components/ModalPage/ModalPageInternal.tsx +2 -1
- package/src/components/ModalPage/types.ts +7 -0
- package/src/components/OnboardingTooltip/OnboardingTooltip.module.css +13 -0
- package/src/components/OnboardingTooltip/OnboardingTooltip.tsx +36 -8
- package/src/components/Pagination/Pagination.tsx +19 -5
- package/src/components/Pagination/PaginationPage/PaginationPageButton.tsx +3 -3
- package/src/components/PanelHeaderButton/PanelHeaderButton.module.css +5 -0
- package/src/components/Removable/Removable.module.css +3 -0
- package/src/components/Removable/Removable.tsx +12 -1
- package/src/components/Search/Search.module.css +1 -0
- package/src/components/SimpleCell/SimpleCell.module.css +2 -0
- package/src/components/SubnavigationButton/SubnavigationButton.module.css +1 -0
- package/src/components/TabbarItem/TabbarItem.tsx +18 -1
- package/src/components/TooltipBase/TooltipBase.module.css +1 -0
- package/src/components/TooltipBase/TooltipBase.tsx +7 -1
- package/src/hooks/useFocusTrap.ts +1 -1
- package/src/types.ts +2 -1
- package/dist/components/Pagination/utils.d.ts +0 -2
- package/dist/components/Pagination/utils.d.ts.map +0 -1
- package/dist/components/Pagination/utils.js +0 -5
- package/dist/components/Pagination/utils.js.map +0 -1
- package/dist/cssm/components/Pagination/utils.js +0 -5
- package/dist/cssm/components/Pagination/utils.js.map +0 -1
- package/src/components/Pagination/utils.ts +0 -3
package/package.json
CHANGED
|
@@ -193,6 +193,11 @@ export const Alert = ({
|
|
|
193
193
|
</IconButton>
|
|
194
194
|
)}
|
|
195
195
|
</div>
|
|
196
|
+
{isDismissButtonVisible && dismissButtonMode === 'outside' && (
|
|
197
|
+
<ModalDismissButton onClick={close} data-testid={dismissButtonTestId}>
|
|
198
|
+
{dismissLabel}
|
|
199
|
+
</ModalDismissButton>
|
|
200
|
+
)}
|
|
196
201
|
<AlertActions
|
|
197
202
|
actions={actions}
|
|
198
203
|
actionsAlign={actionsAlign}
|
|
@@ -200,11 +205,6 @@ export const Alert = ({
|
|
|
200
205
|
renderAction={renderAction}
|
|
201
206
|
onItemClick={onItemClick}
|
|
202
207
|
/>
|
|
203
|
-
{isDismissButtonVisible && dismissButtonMode === 'outside' && (
|
|
204
|
-
<ModalDismissButton onClick={close} data-testid={dismissButtonTestId}>
|
|
205
|
-
{dismissLabel}
|
|
206
|
-
</ModalDismissButton>
|
|
207
|
-
)}
|
|
208
208
|
</FocusTrap>
|
|
209
209
|
</PopoutWrapper>
|
|
210
210
|
</AppRootPortal>
|
|
@@ -335,12 +335,7 @@ export const CarouselBase = ({
|
|
|
335
335
|
|
|
336
336
|
const simpleSlideChangePerform = () => {
|
|
337
337
|
const { snaps } = slidesManager.current;
|
|
338
|
-
|
|
339
|
-
const endPoint = snaps[slideIndex];
|
|
340
|
-
const distance = endPoint - startPoint;
|
|
341
|
-
addToAnimationQueue(
|
|
342
|
-
getAnimateFunction((progress) => transformCssStyles(startPoint + distance * progress)),
|
|
343
|
-
);
|
|
338
|
+
requestTransform(snaps[slideIndex], true);
|
|
344
339
|
};
|
|
345
340
|
|
|
346
341
|
useIsomorphicLayoutEffect(
|
|
@@ -145,6 +145,7 @@ export const FormItem: React.FC<FormItemProps> & {
|
|
|
145
145
|
}}
|
|
146
146
|
removePlaceholder={removePlaceholder}
|
|
147
147
|
indent={removable === 'indent'}
|
|
148
|
+
noPadding={noPadding}
|
|
148
149
|
>
|
|
149
150
|
<div className={classNames(styles.removable, 'vkuiInternalFormItem__removable')}>
|
|
150
151
|
{wrappedChildren}
|
|
@@ -178,7 +178,6 @@ export const HorizontalScroll = ({
|
|
|
178
178
|
scrollOnAnyWheel = false,
|
|
179
179
|
prevButtonTestId,
|
|
180
180
|
nextButtonTestId,
|
|
181
|
-
getRootRef,
|
|
182
181
|
...restProps
|
|
183
182
|
}: HorizontalScrollProps): React.ReactNode => {
|
|
184
183
|
const [canScrollLeft, setCanScrollLeft] = React.useState(false);
|
|
@@ -192,8 +191,6 @@ export const HorizontalScroll = ({
|
|
|
192
191
|
|
|
193
192
|
const scrollerRef = useExternRef(getRef, directionRef);
|
|
194
193
|
|
|
195
|
-
const rootRef = useExternRef(getRootRef);
|
|
196
|
-
|
|
197
194
|
const animationQueue = React.useRef<VoidFunction[]>([]);
|
|
198
195
|
|
|
199
196
|
const hasPointer = useAdaptivityHasPointer();
|
|
@@ -250,31 +247,40 @@ export const HorizontalScroll = ({
|
|
|
250
247
|
|
|
251
248
|
useIsomorphicLayoutEffect(
|
|
252
249
|
function addWheelEventHandler() {
|
|
253
|
-
|
|
250
|
+
const scrollEl = scrollerRef.current;
|
|
251
|
+
if (!scrollEl) {
|
|
254
252
|
return noop;
|
|
255
253
|
}
|
|
256
254
|
/**
|
|
257
255
|
* Прокрутка с помощью любого колеса мыши
|
|
258
256
|
*/
|
|
259
257
|
const onWheel = (e: WheelEvent) => {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
if (e.deltaY && scrollOnAnyWheel) {
|
|
263
|
-
e.preventDefault();
|
|
264
|
-
}
|
|
258
|
+
scrollerRef.current!.scrollBy({ left: e.deltaX + e.deltaY, behavior: 'auto' });
|
|
259
|
+
e.preventDefault();
|
|
265
260
|
};
|
|
261
|
+
|
|
266
262
|
const listenerOptions = { passive: false };
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
263
|
+
|
|
264
|
+
if (scrollOnAnyWheel) {
|
|
265
|
+
scrollEl.addEventListener('wheel', onWheel, listenerOptions);
|
|
266
|
+
}
|
|
267
|
+
scrollEl.addEventListener('scroll', calculateArrowsVisibility, listenerOptions);
|
|
268
|
+
|
|
269
|
+
return () => {
|
|
270
|
+
if (scrollOnAnyWheel) {
|
|
271
|
+
// @ts-expect-error: TS2769 В интерфейсе EventListenerOptions для wheel нет passive свойства
|
|
272
|
+
scrollEl.removeEventListener('wheel', onWheel, listenerOptions);
|
|
273
|
+
}
|
|
274
|
+
// @ts-expect-error: TS2769 В интерфейсе EventListenerOptions для scroll нет passive свойства
|
|
275
|
+
scrollEl.removeEventListener('scroll', calculateArrowsVisibility, listenerOptions);
|
|
276
|
+
};
|
|
270
277
|
},
|
|
271
|
-
[
|
|
278
|
+
[scrollOnAnyWheel, calculateArrowsVisibility, scrollerRef],
|
|
272
279
|
);
|
|
273
280
|
|
|
274
281
|
return (
|
|
275
282
|
<RootComponent
|
|
276
283
|
{...restProps}
|
|
277
|
-
getRootRef={rootRef}
|
|
278
284
|
baseClassName={classNames(
|
|
279
285
|
styles.host,
|
|
280
286
|
'vkuiInternalHorizontalScroll',
|
|
@@ -306,7 +312,7 @@ export const HorizontalScroll = ({
|
|
|
306
312
|
onClick={scrollToRight}
|
|
307
313
|
/>
|
|
308
314
|
)}
|
|
309
|
-
<div className={styles.in} ref={scrollerRef}
|
|
315
|
+
<div className={styles.in} ref={scrollerRef}>
|
|
310
316
|
<div className={styles.inWrapper}>{children}</div>
|
|
311
317
|
</div>
|
|
312
318
|
</RootComponent>
|
|
@@ -70,6 +70,7 @@ export const ModalCardInternal = ({
|
|
|
70
70
|
onOpened,
|
|
71
71
|
onClose = noop,
|
|
72
72
|
onClosed,
|
|
73
|
+
disableFocusTrap,
|
|
73
74
|
...restProps
|
|
74
75
|
}: ModalCardInternalProps): ReactNode => {
|
|
75
76
|
const platform = usePlatform();
|
|
@@ -136,7 +137,10 @@ export const ModalCardInternal = ({
|
|
|
136
137
|
);
|
|
137
138
|
|
|
138
139
|
useScrollLock(!hidden);
|
|
139
|
-
useFocusTrap(ref, {
|
|
140
|
+
useFocusTrap(ref, {
|
|
141
|
+
autoFocus: !noFocusToDialog,
|
|
142
|
+
disabled: !opened || hidden || disableFocusTrap,
|
|
143
|
+
});
|
|
140
144
|
|
|
141
145
|
return (
|
|
142
146
|
<ModalOutlet hidden={hidden} isDesktop={isDesktop} onKeyDown={handleEscKeyDown}>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { UIEvent } from 'react';
|
|
2
|
+
import { type UseFocusTrapProps } from '../../hooks/useFocusTrap';
|
|
2
3
|
import type { NavIdProps } from '../../lib/getNavId';
|
|
3
4
|
import type { UseBottomSheetHandlers } from '../../lib/sheet';
|
|
4
5
|
import type { ModalCardBaseProps } from '../ModalCardBase/ModalCardBase';
|
|
@@ -48,4 +49,10 @@ export interface ModalCardProps
|
|
|
48
49
|
* Будет вызвано при окончательном закрытии модалки.
|
|
49
50
|
*/
|
|
50
51
|
onClosed?: VoidFunction;
|
|
52
|
+
/**
|
|
53
|
+
* Позволяет отключить захват фокуса.
|
|
54
|
+
*
|
|
55
|
+
* Нужно использовать, когда поверх одной модалки открывается другая, чтобы два `FocusTrap` не конфликтовали
|
|
56
|
+
*/
|
|
57
|
+
disableFocusTrap?: UseFocusTrapProps['disabled'];
|
|
51
58
|
}
|
|
@@ -75,6 +75,7 @@ export const ModalPageInternal = ({
|
|
|
75
75
|
onOpened,
|
|
76
76
|
onClose = noop,
|
|
77
77
|
onClosed,
|
|
78
|
+
disableFocusTrap,
|
|
78
79
|
...restProps
|
|
79
80
|
}: ModalPageInternalProps) => {
|
|
80
81
|
const { hasCustomPanelHeaderAfter } = useConfigProvider();
|
|
@@ -171,7 +172,7 @@ export const ModalPageInternal = ({
|
|
|
171
172
|
autoFocus={!noFocusToDialog}
|
|
172
173
|
role="dialog"
|
|
173
174
|
aria-modal="true"
|
|
174
|
-
disabled={!opened || hidden}
|
|
175
|
+
disabled={!opened || hidden || disableFocusTrap}
|
|
175
176
|
className={classNames(
|
|
176
177
|
className,
|
|
177
178
|
styles.host,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CSSProperties, ReactNode, Ref, UIEvent } from 'react';
|
|
2
|
+
import { type UseFocusTrapProps } from '../../hooks/useFocusTrap';
|
|
2
3
|
import type { NavIdProps } from '../../lib/getNavId';
|
|
3
4
|
import type { HTMLAttributesWithRootRef } from '../../types';
|
|
4
5
|
|
|
@@ -109,4 +110,10 @@ export interface ModalPageProps
|
|
|
109
110
|
* Будет вызвано при окончательном закрытии модалки.
|
|
110
111
|
*/
|
|
111
112
|
onClosed?: VoidFunction;
|
|
113
|
+
/**
|
|
114
|
+
* Позволяет отключить захват фокуса.
|
|
115
|
+
*
|
|
116
|
+
* Нужно использовать, когда поверх одной модалки открывается другая, чтобы два `FocusTrap` не конфликтовали
|
|
117
|
+
*/
|
|
118
|
+
disableFocusTrap?: UseFocusTrapProps['disabled'];
|
|
112
119
|
}
|
|
@@ -4,4 +4,17 @@
|
|
|
4
4
|
inset-block-start: 0;
|
|
5
5
|
inline-size: 100%;
|
|
6
6
|
block-size: 100%;
|
|
7
|
+
padding: 0;
|
|
8
|
+
margin: 0;
|
|
9
|
+
appearance: none;
|
|
10
|
+
-webkit-touch-callout: none;
|
|
11
|
+
-webkit-user-drag: none;
|
|
12
|
+
cursor: default;
|
|
13
|
+
background: transparent;
|
|
14
|
+
border: 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.overlay:focus,
|
|
18
|
+
.overlay:focus-visible {
|
|
19
|
+
outline: none;
|
|
7
20
|
}
|
|
@@ -4,6 +4,7 @@ import * as React from 'react';
|
|
|
4
4
|
import { hasReactNode } from '@vkontakte/vkjs';
|
|
5
5
|
import { mergeStyle } from '../../helpers/mergeStyle';
|
|
6
6
|
import { useExternRef } from '../../hooks/useExternRef';
|
|
7
|
+
import { type UseFocusTrapProps } from '../../hooks/useFocusTrap';
|
|
7
8
|
import { usePatchChildren } from '../../hooks/usePatchChildren';
|
|
8
9
|
import { createPortal } from '../../lib/createPortal';
|
|
9
10
|
import {
|
|
@@ -18,6 +19,7 @@ import { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';
|
|
|
18
19
|
import { warnOnce } from '../../lib/warnOnce';
|
|
19
20
|
import { DEFAULT_ARROW_HEIGHT, DEFAULT_ARROW_PADDING } from '../FloatingArrow/DefaultIcon';
|
|
20
21
|
import type { FloatingArrowProps } from '../FloatingArrow/FloatingArrow';
|
|
22
|
+
import { FocusTrap } from '../FocusTrap/FocusTrap';
|
|
21
23
|
import { useNavTransition } from '../NavTransitionContext/NavTransitionContext';
|
|
22
24
|
import { TOOLTIP_MAX_WIDTH, TooltipBase, type TooltipBaseProps } from '../TooltipBase/TooltipBase';
|
|
23
25
|
import { onboardingTooltipContainerAttr } from './OnboardingTooltipContainer';
|
|
@@ -58,7 +60,8 @@ type AllowedFloatingArrowProps = {
|
|
|
58
60
|
export interface OnboardingTooltipProps
|
|
59
61
|
extends AllowedFloatingComponentProps,
|
|
60
62
|
AllowedTooltipBaseProps,
|
|
61
|
-
AllowedFloatingArrowProps
|
|
63
|
+
AllowedFloatingArrowProps,
|
|
64
|
+
Pick<UseFocusTrapProps, 'restoreFocus'> {
|
|
62
65
|
/**
|
|
63
66
|
* Скрывает стрелку, указывающую на якорный элемент.
|
|
64
67
|
*/
|
|
@@ -67,15 +70,19 @@ export interface OnboardingTooltipProps
|
|
|
67
70
|
* Callback, который вызывается при клике по любому месту в пределах экрана.
|
|
68
71
|
*/
|
|
69
72
|
onClose?: (this: void) => void;
|
|
73
|
+
/**
|
|
74
|
+
* [a11y] Метка для подложки-кнопки, для описания того, что произойдёт при клике.
|
|
75
|
+
*/
|
|
76
|
+
overlayLabel?: string;
|
|
70
77
|
}
|
|
71
78
|
|
|
72
79
|
/**
|
|
73
80
|
* @see https://vkcom.github.io/VKUI/#/Tooltip
|
|
74
81
|
*/
|
|
75
82
|
export const OnboardingTooltip = ({
|
|
76
|
-
id: idProp,
|
|
83
|
+
'id': idProp,
|
|
77
84
|
children,
|
|
78
|
-
shown: shownProp = true,
|
|
85
|
+
'shown': shownProp = true,
|
|
79
86
|
arrowPadding = DEFAULT_ARROW_PADDING,
|
|
80
87
|
arrowHeight = DEFAULT_ARROW_HEIGHT,
|
|
81
88
|
offsetByMainAxis = 0,
|
|
@@ -83,13 +90,18 @@ export const OnboardingTooltip = ({
|
|
|
83
90
|
arrowOffset = 0,
|
|
84
91
|
isStaticArrowOffset = false,
|
|
85
92
|
onClose,
|
|
86
|
-
placement: placementProp = 'bottom-start',
|
|
93
|
+
'placement': placementProp = 'bottom-start',
|
|
87
94
|
maxWidth = TOOLTIP_MAX_WIDTH,
|
|
88
|
-
style: styleProp,
|
|
95
|
+
'style': styleProp,
|
|
89
96
|
getRootRef,
|
|
90
97
|
disableArrow = false,
|
|
91
98
|
onPlacementChange,
|
|
92
99
|
disableFlipMiddleware = false,
|
|
100
|
+
overlayLabel = 'Закрыть',
|
|
101
|
+
title,
|
|
102
|
+
'aria-label': ariaLabel,
|
|
103
|
+
'aria-labelledby': ariaLabelledBy,
|
|
104
|
+
restoreFocus,
|
|
93
105
|
...restProps
|
|
94
106
|
}: OnboardingTooltipProps): React.ReactNode => {
|
|
95
107
|
const generatedId = React.useId();
|
|
@@ -130,6 +142,13 @@ export const OnboardingTooltip = ({
|
|
|
130
142
|
|
|
131
143
|
usePlacementChangeCallback(placementProp, resolvedPlacement, onPlacementChange);
|
|
132
144
|
|
|
145
|
+
const titleId = React.useId();
|
|
146
|
+
if (process.env.NODE_ENV === 'development' && !title && !ariaLabel && !ariaLabelledBy) {
|
|
147
|
+
warn(
|
|
148
|
+
'Если "title" не используется, то необходимо задать либо "aria-label", либо "aria-labelledby" (см. правило axe aria-dialog-name)',
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
133
152
|
let tooltip: React.ReactPortal | null = null;
|
|
134
153
|
if (shown) {
|
|
135
154
|
const floatingStyle = convertFloatingDataToReactCSSProperties(
|
|
@@ -139,10 +158,20 @@ export const OnboardingTooltip = ({
|
|
|
139
158
|
);
|
|
140
159
|
|
|
141
160
|
tooltip = createPortal(
|
|
142
|
-
|
|
161
|
+
<FocusTrap
|
|
162
|
+
role="dialog"
|
|
163
|
+
aria-modal="true"
|
|
164
|
+
aria-label={ariaLabel}
|
|
165
|
+
aria-labelledby={title ? titleId : ariaLabel ? undefined : ariaLabelledBy}
|
|
166
|
+
onClose={onClose}
|
|
167
|
+
restoreFocus={restoreFocus}
|
|
168
|
+
>
|
|
169
|
+
<button aria-label={overlayLabel} className={styles.overlay} onClickCapture={onClose} />
|
|
143
170
|
<TooltipBase
|
|
144
171
|
{...restProps}
|
|
145
172
|
id={tooltipId}
|
|
173
|
+
title={title}
|
|
174
|
+
titleId={title ? titleId : undefined}
|
|
146
175
|
getRootRef={tooltipRef}
|
|
147
176
|
style={mergeStyle(floatingStyle, styleProp)}
|
|
148
177
|
maxWidth={maxWidth}
|
|
@@ -158,8 +187,7 @@ export const OnboardingTooltip = ({
|
|
|
158
187
|
}
|
|
159
188
|
}
|
|
160
189
|
/>
|
|
161
|
-
|
|
162
|
-
</>,
|
|
190
|
+
</FocusTrap>,
|
|
163
191
|
tooltipContainer,
|
|
164
192
|
);
|
|
165
193
|
}
|
|
@@ -17,7 +17,6 @@ import {
|
|
|
17
17
|
PaginationPageButton,
|
|
18
18
|
} from './PaginationPage/PaginationPageButton';
|
|
19
19
|
import { PaginationPageEllipsis } from './PaginationPage/PaginationPageEllipsis';
|
|
20
|
-
import { getPageLabelDefault } from './utils';
|
|
21
20
|
import styles from './Pagination.module.css';
|
|
22
21
|
|
|
23
22
|
export interface PaginationProps extends Omit<HTMLAttributesWithRootRef<HTMLElement>, 'onChange'> {
|
|
@@ -76,6 +75,12 @@ export interface PaginationProps extends Omit<HTMLAttributesWithRootRef<HTMLElem
|
|
|
76
75
|
nextButtonLabel?: string;
|
|
77
76
|
/**
|
|
78
77
|
* [a11y] Функция для переопределения и/или локализации метки кнопки страницы.
|
|
78
|
+
*
|
|
79
|
+
* > Note: По возможности лучше не использовать,
|
|
80
|
+
* так как компонент и так проставляет номер страницы в разметку,
|
|
81
|
+
* что достаточно для пользователей скринридеров.
|
|
82
|
+
* Дополнительная информация скорее будет избыточна,
|
|
83
|
+
* так как будет зачитываться для каждой кнопки при перемещении по списку.
|
|
79
84
|
*/
|
|
80
85
|
getPageLabel?: (isCurrent: boolean) => string;
|
|
81
86
|
onChange?: (page: number, event: React.MouseEvent<HTMLElement>) => void;
|
|
@@ -117,8 +122,8 @@ export const Pagination = ({
|
|
|
117
122
|
prevButtonCaption = 'Назад',
|
|
118
123
|
nextButtonCaption = 'Вперёд',
|
|
119
124
|
navigationButtonsStyle = 'icon',
|
|
120
|
-
getPageLabel
|
|
121
|
-
navigationLabel = '
|
|
125
|
+
getPageLabel,
|
|
126
|
+
navigationLabel = 'Страницы',
|
|
122
127
|
navigationLabelComponent = 'h2',
|
|
123
128
|
prevButtonLabel = 'Перейти на предыдущую страницу',
|
|
124
129
|
nextButtonLabel = 'Перейти на следующую страницу',
|
|
@@ -204,9 +209,18 @@ export const Pagination = ({
|
|
|
204
209
|
[currentPage, disabled, getPageLabel, handleClick, renderPageButton, sizeY, pageButtonTestId],
|
|
205
210
|
);
|
|
206
211
|
|
|
212
|
+
const navigationLabelId = React.useId();
|
|
213
|
+
|
|
207
214
|
return (
|
|
208
|
-
<RootComponent
|
|
209
|
-
|
|
215
|
+
<RootComponent
|
|
216
|
+
Component="nav"
|
|
217
|
+
role="navigation"
|
|
218
|
+
aria-labelledby={navigationLabelId}
|
|
219
|
+
{...resetProps}
|
|
220
|
+
>
|
|
221
|
+
<VisuallyHidden id={navigationLabelId} Component={navigationLabelComponent}>
|
|
222
|
+
{navigationLabel}
|
|
223
|
+
</VisuallyHidden>
|
|
210
224
|
<ul className={styles.list}>
|
|
211
225
|
<li className={styles.prevButtonContainer}>
|
|
212
226
|
<PaginationNavigationButton
|
|
@@ -5,7 +5,6 @@ import { Tappable, type TappableProps } from '../../Tappable/Tappable';
|
|
|
5
5
|
import { Text } from '../../Typography/Text/Text';
|
|
6
6
|
import { VisuallyHidden } from '../../VisuallyHidden/VisuallyHidden';
|
|
7
7
|
import type { PaginationProps } from '../Pagination';
|
|
8
|
-
import { getPageLabelDefault } from '../utils';
|
|
9
8
|
import { getPaginationPageClassNames } from './usePaginationPageClasses';
|
|
10
9
|
import styles from './PaginationPage.module.css';
|
|
11
10
|
|
|
@@ -26,7 +25,7 @@ const getTappablePropsFromPaginationPage = (
|
|
|
26
25
|
): TappableProps & { 'data-page': number } => {
|
|
27
26
|
const {
|
|
28
27
|
isCurrent = false,
|
|
29
|
-
getPageLabel
|
|
28
|
+
getPageLabel,
|
|
30
29
|
children,
|
|
31
30
|
className,
|
|
32
31
|
disabled,
|
|
@@ -40,6 +39,7 @@ const getTappablePropsFromPaginationPage = (
|
|
|
40
39
|
sizeY,
|
|
41
40
|
});
|
|
42
41
|
|
|
42
|
+
const pageLabel = getPageLabel?.(isCurrent);
|
|
43
43
|
return {
|
|
44
44
|
'className': classNames(pageClassNames, className),
|
|
45
45
|
'activeMode': styles.stateActive,
|
|
@@ -49,7 +49,7 @@ const getTappablePropsFromPaginationPage = (
|
|
|
49
49
|
'disabled': disabled,
|
|
50
50
|
'children': (
|
|
51
51
|
<Text normalize={false}>
|
|
52
|
-
<VisuallyHidden>{
|
|
52
|
+
{pageLabel && <VisuallyHidden>{pageLabel} </VisuallyHidden>}
|
|
53
53
|
{children}
|
|
54
54
|
</Text>
|
|
55
55
|
),
|
|
@@ -150,6 +150,10 @@ interface RemovableOwnProps
|
|
|
150
150
|
* @since 5.4.0
|
|
151
151
|
*/
|
|
152
152
|
indent?: boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Убирает базовые отступы для базовой платформы
|
|
155
|
+
*/
|
|
156
|
+
noPadding?: boolean;
|
|
153
157
|
children?: React.ReactNode | ((renderProps: RemovableIosRenderProps) => React.ReactNode);
|
|
154
158
|
}
|
|
155
159
|
|
|
@@ -165,6 +169,7 @@ export const Removable = ({
|
|
|
165
169
|
toggleButtonTestId,
|
|
166
170
|
removeButtonTestId,
|
|
167
171
|
disabled,
|
|
172
|
+
noPadding,
|
|
168
173
|
...restProps
|
|
169
174
|
}: RemovableOwnProps): React.ReactNode => {
|
|
170
175
|
const platform = usePlatform();
|
|
@@ -186,7 +191,13 @@ export const Removable = ({
|
|
|
186
191
|
)}
|
|
187
192
|
>
|
|
188
193
|
{platform !== 'ios' && (
|
|
189
|
-
<div
|
|
194
|
+
<div
|
|
195
|
+
className={classNames(
|
|
196
|
+
styles.content,
|
|
197
|
+
!noPadding && styles.withPadding,
|
|
198
|
+
'vkuiInternalRemovable__content',
|
|
199
|
+
)}
|
|
200
|
+
>
|
|
190
201
|
{typeof children === 'function' ? children({ isRemoving: false }) : children}
|
|
191
202
|
|
|
192
203
|
<IconButton
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
|
|
33
33
|
/* stylelint-disable-next-line selector-pseudo-class-disallowed-list */
|
|
34
34
|
.before > :global(.vkuiIcon) {
|
|
35
|
+
box-sizing: content-box;
|
|
35
36
|
padding-inline-end: var(--vkui--spacing_size_xs);
|
|
36
37
|
}
|
|
37
38
|
|
|
@@ -125,6 +126,7 @@
|
|
|
125
126
|
|
|
126
127
|
/* stylelint-disable-next-line selector-pseudo-class-disallowed-list */
|
|
127
128
|
.after > :global(.vkuiIcon) {
|
|
129
|
+
box-sizing: content-box;
|
|
128
130
|
padding-inline-start: var(--vkui--spacing_size_m);
|
|
129
131
|
}
|
|
130
132
|
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { classNames, hasReactNode, noop } from '@vkontakte/vkjs';
|
|
5
|
+
import { useFocusVisible } from '../../hooks/useFocusVisible';
|
|
6
|
+
import { useFocusVisibleClassName } from '../../hooks/useFocusVisibleClassName';
|
|
5
7
|
import { usePlatform } from '../../hooks/usePlatform';
|
|
8
|
+
import { callMultiple } from '../../lib/callMultiple';
|
|
6
9
|
import { COMMON_WARNINGS, warnOnce } from '../../lib/warnOnce';
|
|
7
10
|
import type { HasComponent, HasRootRef } from '../../types';
|
|
8
11
|
import { RootComponent } from '../RootComponent/RootComponent';
|
|
@@ -38,6 +41,8 @@ export const TabbarItem = ({
|
|
|
38
41
|
href,
|
|
39
42
|
Component = href ? 'a' : 'button',
|
|
40
43
|
disabled,
|
|
44
|
+
onFocus: onFocusProp,
|
|
45
|
+
onBlur: onBlurProp,
|
|
41
46
|
...restProps
|
|
42
47
|
}: TabbarItemProps): React.ReactNode => {
|
|
43
48
|
const platform = usePlatform();
|
|
@@ -50,11 +55,22 @@ export const TabbarItem = ({
|
|
|
50
55
|
}
|
|
51
56
|
}
|
|
52
57
|
|
|
58
|
+
const {
|
|
59
|
+
focusVisible,
|
|
60
|
+
onFocus: handleFocusVisibleOnFocus,
|
|
61
|
+
onBlur: handleFocusVisibleOnBlur,
|
|
62
|
+
} = useFocusVisible();
|
|
63
|
+
const focusVisibleClassNames = useFocusVisibleClassName({
|
|
64
|
+
focusVisible,
|
|
65
|
+
});
|
|
66
|
+
|
|
53
67
|
return (
|
|
54
68
|
<RootComponent
|
|
55
69
|
Component={Component}
|
|
56
70
|
{...restProps}
|
|
57
71
|
disabled={disabled}
|
|
72
|
+
onFocus={callMultiple(handleFocusVisibleOnFocus, onFocusProp)}
|
|
73
|
+
onBlur={callMultiple(handleFocusVisibleOnBlur, onBlurProp)}
|
|
58
74
|
href={href}
|
|
59
75
|
baseClassName={classNames(
|
|
60
76
|
styles.host,
|
|
@@ -69,8 +85,9 @@ export const TabbarItem = ({
|
|
|
69
85
|
activeMode={platform === 'ios' ? styles.tappableActive : 'background'}
|
|
70
86
|
activeEffectDelay={platform === 'ios' ? 0 : 300}
|
|
71
87
|
hasHover={false}
|
|
72
|
-
className={styles.tappable}
|
|
88
|
+
className={classNames(styles.tappable, focusVisibleClassNames)}
|
|
73
89
|
onClick={noop}
|
|
90
|
+
tabIndex={-1}
|
|
74
91
|
/>
|
|
75
92
|
<div className={styles.in}>
|
|
76
93
|
<div className={styles.icon}>
|
|
@@ -35,6 +35,11 @@ export interface TooltipBaseProps
|
|
|
35
35
|
* Заголовок тултипа.
|
|
36
36
|
*/
|
|
37
37
|
title?: React.ReactNode;
|
|
38
|
+
/**
|
|
39
|
+
* [a11y] Id для заголовка тултипа.
|
|
40
|
+
* Можно использовать для связи элемента с `role="dialog"` и заголовка через `aria-labelledby`
|
|
41
|
+
*/
|
|
42
|
+
titleId?: string;
|
|
38
43
|
/**
|
|
39
44
|
* Для показа указателя, требуется передать хотя бы `coords` и `placement`.
|
|
40
45
|
*/
|
|
@@ -85,6 +90,7 @@ export const TooltipBase = ({
|
|
|
85
90
|
ArrowIcon = DefaultIcon,
|
|
86
91
|
description,
|
|
87
92
|
title,
|
|
93
|
+
titleId,
|
|
88
94
|
maxWidth = TOOLTIP_MAX_WIDTH,
|
|
89
95
|
closeIconLabel = 'Закрыть',
|
|
90
96
|
onCloseIconClick,
|
|
@@ -111,7 +117,7 @@ export const TooltipBase = ({
|
|
|
111
117
|
<div className={styles.content} style={maxWidth !== null ? { maxWidth } : undefined}>
|
|
112
118
|
<div>
|
|
113
119
|
{hasReactNode(title) && (
|
|
114
|
-
<Subhead className={styles.title} weight="2">
|
|
120
|
+
<Subhead id={titleId} className={styles.title} weight="2">
|
|
115
121
|
{title}
|
|
116
122
|
</Subhead>
|
|
117
123
|
)}
|
|
@@ -166,7 +166,7 @@ export const useFocusTrap = (
|
|
|
166
166
|
|
|
167
167
|
recalculateFocusableNodesRef(parentNode);
|
|
168
168
|
|
|
169
|
-
if (!autoFocus || arraysEquals(oldFocusableNodes, focusableNodesRef.current)) {
|
|
169
|
+
if (disabled || !autoFocus || arraysEquals(oldFocusableNodes, focusableNodesRef.current)) {
|
|
170
170
|
return;
|
|
171
171
|
}
|
|
172
172
|
|
package/src/types.ts
CHANGED
|
@@ -51,7 +51,8 @@ export interface Version {
|
|
|
51
51
|
export type AnchorHTMLAttributesOnly = Omit<
|
|
52
52
|
React.AnchorHTMLAttributes<HTMLAnchorElement>,
|
|
53
53
|
keyof React.HTMLAttributes<HTMLAnchorElement>
|
|
54
|
-
|
|
54
|
+
> &
|
|
55
|
+
React.AriaAttributes;
|
|
55
56
|
|
|
56
57
|
/**
|
|
57
58
|
* Проверяет, является ли тип подтипом другого.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/components/Pagination/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CAE9D"}
|