Отрисовка элемента панели инструментов по заданному c Ref - PullRequest
0 голосов
/ 27 мая 2020

Я хочу отображать свой TooltipComponent на кнопке, только когда пользователь нажимает на эту кнопку и задает условие c.

Я знаком с библиотекой react-tooltip, но не Не хочу его использовать, мое мнение об этой библиотеке не положительное. В этой библиотеке есть функция ReactTooltop.show.

Я хочу иметь возможность делать что-то вроде (опять же, без использования этой библиотеки:

const onBtnClick = () => {
    if(...condition...){
       MyTooltip.show(btnRef, ...); // maybe pass some arguments like tooltip text...
    }
}

Любая идея, как я могу это реализовать ?

Спасибо!

1 Ответ

1 голос
/ 27 мая 2020

Что вам нужно, это popover, вот пример . Вы можете найти некоторые из них на inte rnet, но их также легко воссоздать:

.ts:

import React, { Component } from "react";
import { render } from "react-dom";
import "./style.css";

const App = () => {
  const [isPopoverVisible, setPopoverVisibility] = React.useState(false);
  const togglePopover = () => {
    if (!isPopoverVisible) {
      setPopoverVisibility(!isPopoverVisible);
    } else {
      setTimeout(() => setPopoverVisibility(!isPopoverVisible), 20000);
    }
  };

  return (
    <>
      <div>
        Content Content Content Content Content Content Content Content Content
        Content Content Content Content Content Content Content Content Content
        Content Content Content Content Content Content Content Content Content
        Content Content Content Content Content Content Content Content Content
        Content Content Content Content
      </div>
      <span>Some content</span>
      <Popover
        isVisible={isPopoverVisible}
        resetVisibility={togglePopover}
      >
        <button onClick={() => togglePopover()}>coucou</button>
      </Popover>
      <div>other content</div>
    </>
  );
};

const Popover = ({ children, isVisible, resetVisibility, position }) => {
  const [classes, setClasses] = React.useState("popover");
  const [style, setStyle] = React.useState({});
  const childrenRef = React.createRef();
  const popoverMessageRef = React.createRef();

  React.useEffect(() => {
    const messagePos = popoverMessageRef.current.getBoundingClientRect();
    const childrenPos = childrenRef.current.getBoundingClientRect();

    // x and y from getBoundingClientRect() dos not take into account the padding, we need to add it to our calculs
    const messagePaddingFull = window
      .getComputedStyle(popoverMessageRef.current)
      .getPropertyValue("padding");
    const messagePadding = 
      messagePaddingFull.substring(0, messagePaddingFull.length - 2);

  if(position){
     if (position.toLowerCase() === "top") {
      setStyle({
        top: `${childrenPos.y - messagePos.height - 10}px`,
        left: `${(childrenPos.x - messagePadding) - childrenPos.width / 2}px`
      });
    } else if(position.toLowerCase() === "left"){
      setStyle({
        top: `${(+childrenPos.y + +messagePadding/2) - childrenPos.height / 2}px`,
        left: `${(childrenPos.x) - messagePos.width - 10}px`
      });
    } else if(position.toLowerCase() === "right"){
      setStyle({
        top: `${(+childrenPos.y + +messagePadding/2) - childrenPos.height / 2}px`,
        left: `${+childrenPos.x + +childrenPos.width + 10}px`
      });
    } else {
      // default bottom
      setStyle({
        top: `${(childrenPos.y) + childrenPos.height + 10}px`,
        left: `${(childrenPos.x  - messagePadding/2) - childrenPos.width / 2}px`
      });
    }
  } else {
      // default bottom position
      setStyle({
        top: `${(childrenPos.y) + childrenPos.height + 10}px`,
        left: `${(childrenPos.x - messagePadding/2) - childrenPos.width / 2}px`
      });
    }

    console.log("messagePos = ", messagePos);
    console.log("messagePos = ", messagePadding);
    console.log("childrenPos = ", childrenPos);
  }, [classes]);

  React.useEffect(() => {
    setClasses(`popover ${isVisible ? "pop" : ""}`);

    if (isVisible) {
      resetVisibility();
    }
  }, [isVisible]);

  return (
    <div className="popover-component">
      <span ref={childrenRef}>{children}</span>
      <div className={classes} ref={popoverMessageRef} style={style}>
        This is the popover
      </div>
    </div>
  );
};

render(<App />, document.getElementById("root"));

. css:

.popover-component{
  display: inline-block;
  position: relative;
}
.popover{
  display: none;
  position: fixed; /* You can play with absolute position as well */
  background-color: #797979;
  border-radius: 4px;
  padding: 5px;
}

.pop {
  display: block; /* You can play with inline-block as well */
}

Вот репродукция на stackblitz . Затем вы можете настроить всплывающее окно, получив ширину детей и поиграв с ней (например, воссоздав параметры «верх», «низ», «левый», «правый», изменив свой al go).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...