'use client'; import * as React from 'react'; import { Icon16Cancel } from '@vkontakte/icons'; import { classNames, hasReactNode } from '@vkontakte/vkjs'; import type { HTMLAttributesWithRootRef } from '../../types'; import { DefaultIcon } from '../FloatingArrow/DefaultIcon'; import { FloatingArrow, type FloatingArrowProps } from '../FloatingArrow/FloatingArrow'; import { RootComponent } from '../RootComponent/RootComponent'; import { Tappable } from '../Tappable/Tappable'; import { Subhead } from '../Typography/Subhead/Subhead'; import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden'; import styles from './TooltipBase.module.css'; export const TOOLTIP_MAX_WIDTH = 220; const stylesAppearance = { accent: styles.appearanceAccent, white: styles.appearanceWhite, black: styles.appearanceBlack, inversion: styles.appearanceInversion, }; export interface TooltipBaseProps extends Omit, 'children' | 'title'> { /** * Стиль отображения подсказки. */ appearance?: 'accent' | 'neutral' | 'white' | 'black' | 'inversion'; /** * Текст тултипа. */ description?: React.ReactNode; /** * Заголовок тултипа. */ title?: React.ReactNode; /** * [a11y] Id для заголовка тултипа. * Можно использовать для связи элемента с `role="dialog"` и заголовка через `aria-labelledby`. */ titleId?: string; /** * Для показа указателя, требуется передать хотя бы `coords` и `placement`. */ arrowProps?: Omit; /** * Пользовательская SVG иконка. * * Требования: * * 1. Иконка по умолчанию должна быть направлена вверх (a.k.a `IconUp`). * 2. Чтобы избежать проблемы с пространством между стрелкой и контентом на некоторых экранах, * растяните кривую по высоте на `1px` и увеличьте на этот размер `height` и `viewBox` SVG. * (смотри https://github.com/VKCOM/VKUI/pull/4496). * 3. Убедитесь, что компонент принимает все валидные для SVG параметры. * 4. Убедитесь, что SVG и её элементы наследует цвет через `fill="currentColor"`. * 5. Если стрелка наезжает на якорный элемент, то увеличьте смещение между целевым и всплывающим элементами. */ ArrowIcon?: FloatingArrowProps['Icon']; /** * Пользовательские css-классы, будут добавлены на root-элемент. */ className?: string; /** * Перебивает максимальную ширину заданную по умолчанию. * * Передача `null` полностью сбрасывает установку `max-width` на элемент. */ maxWidth?: number | string | null; /** * Скрытый текст для кнопки закрытия. */ closeIconLabel?: string; /** * Обработчик нажатия на кнопку закрытия. При передаче, показывается иконка. */ onCloseIconClick?: (event: React.MouseEvent) => void; } /** * Низкоуровневый компонент для отрисовки тултипа. * @private */ export const TooltipBase = ({ appearance = 'accent', arrowProps, ArrowIcon = DefaultIcon, description, title, titleId, maxWidth = TOOLTIP_MAX_WIDTH, closeIconLabel = 'Закрыть', onCloseIconClick, className, ...restProps }: TooltipBaseProps): React.ReactNode => { return ( {arrowProps && ( )}
{hasReactNode(title) && ( {title} )} {hasReactNode(description) && ( {description} )}
{typeof onCloseIconClick === 'function' && ( {closeIconLabel} )}
); };