npm.io
0.15.8 • Published 1 month ago

@snack-uikit/popover-private

Licence
Apache-2.0
Version
0.15.8
Deps
5
Size
118 kB
Vulns
0
Weekly
0
Stars
23

Popover Private

Installation

npm i @snack-uikit/popover-private

Changelog

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>
  </>
)