Categories
React

react-overlays — Tooltips

Tooltips are something that we have to add often into our React app.

To make this task easier, we can use existing component libraries to add them.

In this article, we’ll look at how to add tooltips into our React app with the react-overlays library.

Ovelays

We can add overlays easily with the Overlay component.

To add it, we can write:

import React, { useReducer, useRef, useState } from "react";
import styled from "styled-components";
import Overlay from "react-overlays/Overlay";

const Tooltip = styled("div")`
  position: absolute;
`;

const Arrow = styled("div")`
  position: absolute;
  width: 10px;
  height: 10px;
  z-index: -1;

  &::before {
    content: "";
    position: absolute;
    transform: rotate(45deg);
    background: #000;
    width: 10px;
    height: 10px;
    top: 0;
    left: 0;
  }

  ${(p) =>
    ({
      left: "right: -4px;",
      right: "left: -4px;",
      top: "bottom: -4px;",
      bottom: "top: -4px;"
    }[p.placement])}
`;

const Body = styled("div")`
  padding: 3px 8px;
  color: #fff;
  text-align: center;
  border-radius: 3px;
  background-color: #000;
`;

const PLACEMENTS = ["left", "top", "right", "bottom"];

const initialSstate = {
  show: false,
  placement: null
};

function reducer(state, [type, payload]) {
  switch (type) {
    case "placement":
      return { show: !!payload, placement: payload };
    case "hide":
      return { ...state, show: false, placement: null };
    default:
      return state;
  }
}

export default function App() {
  const [{ show, placement }, dispatch] = useReducer(reducer, initialSstate);
  const triggerRef = useRef(null);
  const containerRef = useRef(null);

  const handleClick = () => {
    const nextPlacement = PLACEMENTS[PLACEMENTS.indexOf(placement) + 1];

dispatch(["placement", nextPlacement]);
  };

  return (
    <div className="flex flex-col items-center" ref={containerRef}>
      <button
        type="button"
        className="btn mb-4"
        id="overlay-toggle"
        ref={triggerRef}
        onClick={handleClick}
        style={{ marginTop: 200, marginLeft: 200 }}
      >
        I am an Overlay target
      </button>
      <Overlay
        show={show}
        rootClose
        offset={[0, 10]}
        onHide={() => dispatch("hide")}
        placement={placement}
        container={containerRef}
        target={triggerRef}
      >
        {({ props, arrowProps, placement }) => (
          <Tooltip {...props} placement={placement}>
            <Arrow
              {...arrowProps}
              placement={placement}
              style={arrowProps.style}
            />
            <Body>
              <strong>{placement}</strong>
            </Body>
          </Tooltip>
        )}
      </Overlay>
    </div>
  );
}

We create the Tooltip component to add the tooltip container.

Then we add the Arrow component to add the arrow for the tooltip.

The Arrow is the child of Tooltip so that it’s attached to the tooltip.

The Body component is a div that has the content of the tooltip.

We can set the placement state to set the placement of the tooltip.

Its value is passed into the placement prop to set the placement.

The possible values are 'left' , 'top' , 'right' , and 'bottom' .

The Overlay component takes a few props to let us adjust it.

The show prop controls when the overlay is shown.

rootClose lets us close the tooltip when we click outside of it.

offset has the horizontal and vertical offsets.

placement has the placement of the tooltip.

containerRef has the container component for the tooltip.

target has the ref for the component to trigger the tooltip.

Now when we click on the button, we see the tooltip show at different locations each time as we change the placement each time.

Conclusion

We can add tooltips into our React app with the Overlays component provided by the React Overlays library.

Categories
React

react-overlays — Dropdowns

Dropdowns are something that we have to add often into our React app.

To make this task easier, we can use existing component libraries to add them.

In this article, we’ll look at how to add dropdowns into our React app with the react-overlays library.

Dropdowns

We can add dropdowns easily with the Dropdown component and the useDropdownMenu and useDropdownToggle hooks.

For example, we can write:

import React, { useState } from "react";
import styled from "styled-components";
import Dropdown from "react-overlays/Dropdown";
import { useDropdownMenu, useDropdownToggle } from "react-overlays";

const MenuContainer = styled("div")`
  display: ${(p) => (p.show ? "flex" : "none")};
  min-width: 150px;
  position: absolute;
  z-index: 1000;
  flex-direction: column;
  border: 1px solid #e5e5e5;
  background-color: white;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
`;

const Menu = ({ role }) => {
  const { show, onClose, props } = useDropdownMenu({
    flip: true,
    offset: [0, 8]
  });
  return (
    <MenuContainer {...props} role={role} show={show}>
      <button type="button" onClick={onClose}>
        Item 1
      </button>
      <button type="button" onClick={onClose}>
        Item 2
      </button>
    </MenuContainer>
  );
};

const Toggle = ({ id, children }) => {
  const [props, { show, toggle }] = useDropdownToggle();
  return (
    <button type="button" className="btn" id={id} {...props} onClick={toggle}>
      {children}
    </button>
  );
};

const DropdownButton = ({ show, onToggle, drop, alignEnd, title, role }) => (
  <Dropdown
    show={show}
    onToggle={onToggle}
    drop={drop}
    alignEnd={alignEnd}
    itemSelector="button:not(:disabled)"
  >
    {({ props }) => (
      <div {...props} className="relative inline-block">
        <Toggle id="example-toggle">{title}</Toggle>
        <Menu role={role} />
      </div>
    )}
  </Dropdown>
);

const ButtonToolbar = styled("div")`
  & > * + * {
    margin-left: 12px;
  }
`;

export default function App() {
  const [show, setShow] = useState(false);

  return (
    <ButtonToolbar className="dropdown-example">
      <DropdownButton
        show={show}
        onToggle={(nextShow) => setShow(nextShow)}
        title={`${show ? "Close" : "Open"} Dropdown`}
      />
      <DropdownButton alignEnd title="Align right" />
      <DropdownButton drop="up" title="Drop up" />
      <DropdownButton role="menu" title="Role 'menu'" />
    </ButtonToolbar>
  );
}

First, we create the MenuContainer component, which has the menu buttons.

It’s the container for dropdown menus.

It checks the show prop to determine whether it’s shown or not.

And we make it absolute positioned to open in the location where we clicked on the menu button.

Next, we create the Menu component to hose the MenuContainer with buttons that calls onClose when we click the buttons.

This will close the dropdowns.

The onClose function is returned by the useDropdownMenu hook.

We pass all the props returned by the hook to the MenuContainer to control whether it’s opened or closed.

The show function lets us show the menu.

Then we add the Toggle component to add the dropdown toggles.

The children prop has the button content.

And the toggle function lets us toggle the menu.

toggle is returned by the useDropdownToggle prop.

We then add the DropdownButton to incorporate the toggle with the menu to let us close the menu when we click on tyhe button or when we click outside.

The ButtonToolbar component is another div to contain the dropdown buttons.

We add the DropdownButtons to open the dropdown when we click on them.

Conclusion

We can add dropdowns into our React app easily with the react-overlays library.

Categories
React

react-overlays — Modal Transitions

Modals are something that we have to add often into our React app.

To make this task easier, we can use existing component libraries to add them.

In this article, we’ll look at how to add a modal into our React app with the react-overlays library.

Modal Transitions

We can add transition effects when we open a react-overlays modal.

For instance, we can write:

styles.css

.fade {
  opacity: 0;
  transition: opacity 500ms linear;
}

.show {
  opacity: 1;
}

.backdrop.fade.show {
  opacity: 0.5;
}

.dialog {
  position: absolute;
  width: 400;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border: 1px solid #e5e5e5;
  background-color: white;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
  padding: 20px;
}

App.js

import React, { useState } from "react";
import { Transition } from "react-transition-group";
import styled from "styled-components";
import Modal from "react-overlays/Modal";
import "./styles.css";
const FADE_DURATION = 500;

const AModal = styled(Modal)`
  position: fixed;
  width: 400px;
  z-index: 1040;
  top: 20px;
  left: 30px;
  border: 1px solid #e5e5e5;
  background-color: white;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
  padding: 20px;
`;

const fadeStyles = {
  entering: "show",
  entered: "show"
};

const Fade = ({ children, ...props }) => (
  <Transition {...props} timeout={FADE_DURATION}>
    {(status, innerProps) =>
      React.cloneElement(children, {
        ...innerProps,
        className: `fade ${fadeStyles[status]} ${children.props.className}`
      })
    }
  </Transition>
);

export default function App() {
  const [showModal, setShowModal] = useState(false);

return (
    <div className="flex flex-col items-center">
      <button
        type="button"
        className="btn btn-primary mr-3"
        onClick={() => setShowModal((prev) => !prev)}
      >
        Show Animated Modal
      </button>
      <AModal
        show={showModal}
        onHide={() => setShowModal(false)}
        transition={Fade}
        backdropTransition={Fade}
        renderBackdrop={(props) => (
          <div {...props} className="backdrop absolute inset-0 bg-black z-40" />
        )}
        renderDialog={(props) => (
          <div
            {...props}
            className="fixed inset-0 z-50 flex items-center justify-center pointer-events-none"
          >
            <div className="dialog bg-white shadow rounded-lg pointer-events-auto">
              <h4 id="modal-label">I&apos;m fading in!</h4>
              <p>Anim pariatur</p>
              <button
                type="button"
                className="btn"
                onClick={() => setShowModal(false)}
              >
                Close
              </button>
            </div>
          </div>
        )}
      />
    </div>
  );
}

We create the modal with styled-component’s styled function.

We pass in the Modal component from the react-overlays library to create the modal with our own styles.

Also, we set the styles for fading with the fadeStyles object.

We set the fade effect to show during animation.

Then in App , we add the button to let us open the modal by calling setShowModal to true .

We render the items in the modal with the renderDialog prop.

It has a function that returns a component as the value.

Conclusion

We can add transition effects when modals are open when we use react-overlays to add our modal.

Categories
React

Add a Modal to a React App with Styled React Modal and react-overlays

Modals are something that we have to add often into our React app.

To make this task easier, we can use existing component libraries to add them.

In this article, we’ll look at how to add a modal into our React app with the Styled React Modal and react-overlays libraries.

Styled React Modal

The Styled React Modal library lets us add a modal easily into our React app.

To install it, we run:

npm i styled-react-modal

Then we can use it by writing:

import React, { useState } from "react";
import Modal, { ModalProvider } from "styled-react-modal";
import { ThemeProvider } from "styled-components";

const StyledModal = Modal.styled`
  width: 20rem;
  height: 20rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: white;
`;

function FancyModalButton() {
  const [isOpen, setIsOpen] = useState(false);

  function toggleModal(e) {
    setIsOpen(!isOpen);
  }

  return (
    <div>
      <button onClick={toggleModal}>Click me</button>
      <StyledModal
        isOpen={isOpen}
        onBackgroundClick={toggleModal}
        onEscapeKeydown={toggleModal}
      >
        <span>I am a modal!</span>
        <button onClick={toggleModal}>Close me</button>
      </StyledModal>
    </div>
  );
}

export default function App() {
  return (
    <ThemeProvider theme={{}}>
      <ModalProvider>
        <FancyModalButton />
      </ModalProvider>
    </ThemeProvider>
  );
}

We add the FancyModalButton component to add the modal trigger.

Inside the component, we add the StyledModal inside the component.

It’s created from the Modal.style tag.

We control whether StyledModal is open or close with the isOpen prop.

The onBackgroundClick prop lets us run code when the background is clicked.

And onEscapeKeydown lets us run code when the Esc key is pressed.

We just toggle the isOpen state to open or close the modal since we pass that as the value of the isOpen prop.

Then we use the styled modal by passing it inside the ThemeProvider and ModalProvider .

react-overlays

We can use the react-overlays library to add a modal to our React app.

To install it, we run:

npm install react-overlays

with NPM or:

yarn add react-overlays

with Yarn.

Then we can use it by writing:

import React, { useState } from "react";
import styled from "styled-components";
import Modal from "react-overlays/Modal";

const Backdrop = styled.div`
  position: fixed;
  z-index: 1040;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: #000;
  opacity: 0.5;
`;

const AModal = styled(Modal)`
  position: fixed;
  width: 400px;
  z-index: 1040;
  top: 20px;
  left: 30px;
  border: 1px solid #e5e5e5;
  background-color: white;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
  padding: 20px;
`;

export default function App() {
  const [show, setShow] = useState(false);

  const renderBackdrop = (props) => <Backdrop {...props} />;

  return (
    <div className="modal-example">
      <button
        type="button"
        className="btn btn-primary mb-4"
        onClick={() => setShow(true)}
      >
        Open Modal
      </button>

      <AModal
        show={show}
        onHide={() => setShow(false)}
        renderBackdrop={renderBackdrop}
      >
        <div>
          <h4 id="modal-label">Text in a modal</h4>
          <p>Lorem ipsum</p>
        </div>
      </AModal>
    </div>
  );
}

We create the Backdrop component, which is a div with some styles applied.

Then we create the AModal component, which is a modal that has a fixed position.

And we also set the background color and box-shadow to add some effects to show with the modal.

In App , we have a button to open the modal by calling setShow with true .

And we have the AModal component that shows the modal if show is true .

We pass in the Backdrop component as the value of renderBackdrop to render the backdrop.

onHide is called when we hide the modal.

Conclusion

We can add modals easily into our React app with the Styled React Modal and react-overlays libraries.

Categories
React

Add a Modal to a React App with Rodal and Reactjs-popup

Modals are something that we have to add often into our React app.

To make this task easier, we can use existing component libraries to add them.

In this article, we’ll look at how to add a modal into our React app with the Rodal and Reactjs-popup libraries.

Rodal

We can add the Rodal library by running:

npm i rodal --save

Then we can use it by writing:

import React, { useState } from "react";
import Rodal from "rodal";
import "rodal/lib/rodal.css";

export default function App() {
  const [visible, setVisible] = useState(false);

  return (
    <div>
      <div>
        <button onClick={() => setVisible(true)}>show</button>

        <Rodal visible={visible} onClose={() => setVisible(false)}>
          <div>Content</div>
        </Rodal>
      </div>
    </div>
  );
}

We import the Rodal library with its styles.

Then we set the visible prop to the visible state so that we can control when it’s shown.

We set visible to true to show the modal.

onClose is run when we click the close button.

In it, we call setVisible with false to close the modal.

It has many other options available as props.

width sets the wdith. height sets the hrigjt.

showMask controls whether we show a mask.

animation sets the animation type.

enterAnimation and leaveAnimation sets the animation for when the modal is shown or hidden..

duration sets the duration of the animation.

closeOnEsc lets us close the modal when we press escape.

For example, we can use some of them by writing:

import React, { useState } from "react";
import Rodal from "rodal";
import "rodal/lib/rodal.css";

export default function App() {
  const [visible, setVisible] = useState(false);

  return (
    <div>
      <div>
        <button onClick={() => setVisible(true)}>show</button>

        <Rodal
          enterAnimation="zoom"
          leaveAnimation="zoom"
          closeOnEsc
          visible={visible}
          onClose={() => setVisible(false)}
        >
          <div>Content</div>
        </Rodal>
      </div>
    </div>
  );
}

Other animation types available include:

  • fade
  • flip
  • door
  • rotate
  • slideUp
  • slideDown
  • slideLeft
  • slideRight

Reactjs-popup

The Reactjs-popup library lets us add a popup that’s attached to a trigger element.

To install it, we run:

npm i reactjs-popup

Then we can use it by writing:

import React from "react";
import Popup from "reactjs-popup";
import "reactjs-popup/dist/index.css";

export default function App() {
  return (
    <div>
      <div>
        <Popup trigger={<button> Trigger</button>} position="right center">
          <div>Popup content here !!</div>
        </Popup>
      </div>
    </div>
  );
}

We import the Popup component with the associated styles.

Then we set the trigger prop to the trigger element.

position lets us set the position of the popup with a string.

We can add whatever content we want between the tags.

We can also use it to open a modal by adding the modal prop:

import React from "react";
import Popup from "reactjs-popup";
import "reactjs-popup/dist/index.css";

export default function App() {
  return (
    <div>
      <div>
        <Popup trigger={<button> Trigger</button>} modal nested>
          {(close) => (
            <div className="modal">
              <button className="close" onClick={close}>
                &times;
              </button>
              <div className="header"> Modal Title </div>
              <div className="content">Lorem ipsum</div>
              <div className="actions">
                <Popup
                  trigger={<button className="button"> Trigger </button>}
                  position="top center"
                  nested
                >
                  <span>Lorem ipsum</span>
                </Popup>
                <button
                  className="button"
                  onClick={() => {
                    console.log("modal closed ");
                    close();
                  }}
                >
                  close modal
                </button>
              </div>
            </div>
          )}
        </Popup>
      </div>
    </div>
  );
}

The close function is available to let us close the modal.

The nested prop lets us open another modal in the modal.

Conclusion

We can add modals into our React app with the Rodal and react-popup libraries.