Popover Private
Installation
npm i @snack-uikit/popover-private
Description
- Пакет
@snack-uikit/popover-privateпредоставляет низкоуровневый компонентPopoverPrivateдля отображения всплывающих окон (поповеров) относительно триггер-элемента. - Компонент использует библиотеку Floating UI для позиционирования и автоматической адаптации поповера при выходе за границы видимой области.
- Поддерживает различные типы триггеров отображения: клик, ховер, фокус и их комбинации (
click,hover,focus,focusVisible,hoverAndFocus,hoverAndFocusVisible,clickAndFocusVisible). - Позволяет задать 12 вариантов размещения поповера относительно триггера (top, bottom, left, right и их вариации с
-startи-end), а также цепочку резервных позиций (fallbackPlacements) для автоматического переключения при нехватке места. - Поддерживает управляемый и неуправляемый режимы работы через пропы
openиonOpenChange. - Предоставляет гибкие стратегии управления размерами контейнера поповера: автоматические размеры по контенту, привязка к ширине/высоте триггера (
widthStrategy,heightStrategy). - Может отображать стрелку (
hasArrow), указывающую на триггер, с настраиваемыми CSS-классами для стилизации. - Поддерживает различные варианты работы с триггером: оборачивание элемента в
span, передача функции-рендера, использование внешнегоrefбез оборачивания (triggerRef,disableSpanWrapper). - Автоматически закрывается при клике вне поповера, по нажатию
Esc, при навигации по истории браузера (опционально). - Поддерживает задержки открытия и закрытия для триггера
hover(hoverDelayOpen,hoverDelayClose). - Работает с вложенными поповерами через
FloatingTreeиз Floating UI.
Example
import { useRef } from "react";
import { PopoverPrivate } from "@snack-uikit/popover-private";
function App() {
return (
<PopoverPrivate
placement='top'
popoverContent='Не нажимать, опасно!'
trigger='click'
>
<button>Button with popover</button>
</PopoverPrivate>
);
}
// Без оборачивания таргета
function App() {
const triggerRef = useRef(null)
return (
<>
<PopoverPrivate
placement='top'
popoverContent='Не нажимать, опасно!'
trigger='click'
triggerRef={triggerRef}
/>
<button ref={triggerRef}>Button with popover</button>
</>
);
}
PopoverPrivate
Props
| name | type | default value | description |
|---|---|---|---|
| trigger* | enum Trigger: "click", "hover", "focusVisible", "focus", "hoverAndFocusVisible", "hoverAndFocus", "clickAndFocusVisible" |
- | Условие отображения поповера: - click - открывать по клику - hover - открывать по ховеру - focusVisible - открывать по focus-visible - focus - открывать по фокусу - hoverAndFocusVisible - открывать по ховеру и focus-visible - hoverAndFocus - открывать по ховеру и фокусу - clickAndFocusVisible - открывать по клику и focus-visible |
| popoverContent* | ReactNode | ReactNode[] |
- | Контент поповера |
| placement* | enum Placement: "left", "left-start", "left-end", "right", "right-start", "right-end", "top", "top-start", "top-end", "bottom", "bottom-start", "bottom-end" |
top | Положение поповера относительно своего триггера (children). |
| open | boolean |
- | Управляет состоянием показан/не показан. |
| onOpenChange | (isOpen: boolean) => void |
- | Колбек отображения компонента. Срабатывает при изменении состояния open. |
| outsideClick | boolean | OutsideClickHandler |
- | Закрывать ли при клике вне поповера |
| className | string |
- | CSS-класс |
| triggerClassName | string |
- | CSS-класс триггера |
| hasArrow | boolean |
- | Параметр наличия стрелки у поповера. В размеры стрелки встроен отступ. Дополнительный отступ может быть задан параметром offset. У элемента стрелки нет цвета, необходимо задавать его через параметр arrowClassName. |
| arrowContainerClassName | string |
- | CSS-класс контейнера стрелки поповера |
| arrowElementClassName | string |
- | CSS-класс стрелки поповера |
| offset | number |
0 | Отступ поповера от его триггер-элемента (в пикселях). |
| hoverDelayOpen | number |
- | Задержка открытия по ховеру |
| hoverDelayClose | number |
- | Задержка закрытия по ховеру |
| widthStrategy | enum PopoverWidthStrategy: "auto", "gte", "eq" |
auto | Стратегия управления шириной контейнера поповера - auto - соответствует ширине контента, - gte - Great Than or Equal, равен ширине таргета или больше ее, если контент в поповере шире, - eq - Equal, строго равен ширине таргета. |
| heightStrategy | enum PopoverHeightStrategy: "auto", "eq", "lte" |
auto | Стратегия управления высотой контейнера поповера - auto - соответствует высоте контента, - lte - Less Than or Equal, равен высоте таргета или меньше ее, если контент в поповере меньше, - eq - Equal, строго равен высоте таргета. |
| closeOnEscapeKey | boolean |
true | Закрывать ли по нажатию на кнопку Esc |
| triggerClickByKeys | boolean |
true | Вызывается ли попоповер по нажатию клавиш Enter/Space (при trigger = click) |
| fallbackPlacements | Placement[] |
- | Цепочка расположений которая будет применяться к поповеру от первого к последнему если при текущем он не влезает. |
| disableSpanWrapper | boolean |
- | Отключает для isValidElement внешнюю обертку триггера Пригодится для элементов с position: absolute |
| closeOnPopstate | boolean |
- | Закрывать ли поповер при пекреходе по истории браузера |
| triggerRef | ForwardedRef<ReferenceType | HTMLElement> |
- | Ref ссылка на триггер |
| children | ReactNode | ChildrenFunction |
- | Триггер поповера (подробнее читайте ниже) |
children: ReactNode | ChildrenFunction
Референс, относительно которого рисуется поповер. Возможно несколько вариантов:
в
childrenпередан компонент, который принимает в себяref. В таком случае пропсы этого компонента будут дополнены необходимыми для работы триггеров отображения:useHoverTrigger,useClickTrigger,useFocusTrigger.Осторожно,
refбудет перезаписан. Если вы хотите получить ref на children поповера, можете передать ref в параметр triggerRef. Тогда поповер установит туда значение:<PopoverPrivate popoverContent={<div className={style.content}>some tip here</div>} useHoverTrigger triggerRef={(button) => { /* button HTMLElement из children */ }} > <button>some button</button> </PopoverPrivate>в
childrenпередан компонент, который НЕ принимает в себяref. В таком случае компонент будет обернут вspan, который и послужит рефом для поповера.в
childrenпередана функция. Эта функция будет вызвана на каждый рендер, она должна возвращатьReactNode. В параметры принимает ref, который нужно установить в целевой компонент и функциюgetReferenceProps, возвращающую необходимые для ref параметры. Пример:<PopoverPrivate popoverContent={<div className={style.content}>some tip here</div>} useHoverTrigger > {({ getReferenceProps, ref }) => ( <label> Set the value <input ref={ref} {...getReferenceProps({ onClick: onClickInputHandler })} /> </label> )} </PopoverPrivate>в
childrenпередан примитив string, number или React.Fragment. Children будет обернут вspan.childrenне передан в компонент, в таком случае необходимо передатьrefэлемента вtriggerRef, который будет служить триггером для поповера. Пример:
const triggerRef = useRef(null)
return (
<>
<PopoverPrivate
popoverContent={<div className={style.content}>some tip here</div>}
useHoverTrigger
triggerRef={triggerRef}
/>
<button ref={triggerRef}>Click me</button>
</>
)