Categories
React

Add a Modal to a React App with react-modal-video and react-responsive-modal

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-modal-video and react-responsive-modal libraries.

react-modal-video

The react-modal-video library lets us add a video modal into our React app.

To install it, we run:

npm i react-modal-video

Then we can use it by writing:

import React, { useState } from "react";
import ModalVideo from "react-modal-video";
import "react-modal-video/scss/modal-video.scss";

export default function App() {
  const [isOpen, setOpen] = useState(false);

  return (
    <React.Fragment>
      <ModalVideo
        channel="youtube"
        autoplay
        isOpen={isOpen}
        videoId="sSZNLAIL65M"
        onClose={() => setOpen(false)}
      />

      <button className="btn-primary" onClick={() => setOpen(true)}>
        open
      </button>
    </React.Fragment>
  );
}

We add the ModalVideo component to add the video modal.

The channel prop lets us set the site with the video.

autoplay enables autoplay.

isOpen has the modal open state.

videoId has the ID for the video to embed in the modal.

onClose is run when we close the modal.

Other sites supported include Vimeo and Yorku.

We can set the aspect ratio with the ratio prop.

allowFullScreen lets us enable full-screen display.

animationSpeed sets the speed of the animation when we open or close the modal.

We can also set the class names of various parts of the modal with the modalVideo , modalVideoClose , modalVideoBody , modalVideoInner , and other props.

react-responsive-modal

The react-responsive-modal library is another library that lets us add modals into our React app.

To install it, we run:

npm i react-responsive-modal

to install it with NPM.

We can also install it with Yarn by running:

yarn add react-responsive-modal

Then we can use it by writing:

import React, { useState } from "react";
import "react-responsive-modal/styles.css";
import { Modal } from "react-responsive-modal";

export default function App() {
  const [open, setOpen] = useState(false);
  const onOpenModal = () => setOpen(true);
  const onCloseModal = () => setOpen(false);

  return (
    <div>
      <button onClick={onOpenModal}>Open modal</button>
      <Modal open={open} onClose={onCloseModal} center>
        <h2>Simple centered modal</h2>
      </Modal>
    </div>
  );
}

We import the CSS file with the modal styles.

And we have the open state to open the modal when it’s true and close it otherwise.

Then we add the modal with the Modal component.

We pass in the open state as the value of the open prop to control it.

And we set open to false when onClose is run, which is when we close the modal.

center centers the modal in the screen.

The modal content is the children of the Modal component.

Conclusion

The react-modal-video and react-responsive-modal libraries let us add modals easily into our React app.

Categories
React

react-overlays — Portals and Click Outside

Overlays 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 portals and click outside features into our React app with the react-overlays library.

Portal

We can use the Portal component to lets us render content in the location in the DOM that we want.

For instance, we can use it by writing:

import React, { useRef, useState } from "react";
import Portal from "react-overlays/Portal";

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

  let child = <span>But I actually render here!</span>;

  return (
    <div className="flex flex-col items-center">
      <button type="button" className="btn" onClick={() => setShow(true)}>
        Render Child
      </button>
      <div className="bg-brand-200 p-6 rounded-lg shadow my-4">
        <Portal container={containerRef}>{show && child}</Portal>
      </div>
      <div className="bg-brand-200 p-6 rounded-lg shadow " ref={containerRef} />
    </div>
  );
}

We add the button to toggle the show state to show the content of the portal.

The Portal component has the containerRef to set the container for the portal.

This is let us render the portal content in the location of the containerRef .

useRootClose Hook

The useRootClose hook lets us make a component disappear when we click outside it.

To use it, we write:

import React, { useRef, useState } from "react";
import { useRootClose } from "react-overlays";

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

  useRootClose(ref, handleRootClose, {
    disabled: !show
  });

  return (
    <div className="flex flex-col items-center">
      <button type="button" className="btn" onClick={() => setShow(true)}>
        Show
      </button>

      {show && (
        <div ref={ref} className="rounded shadow bg-white p-6">
          <span>Click anywhere to dismiss</span>
        </div>
      )}
    </div>
  );
}

We add the button to show the div by setting show to true .

Then we add a div that’s shown when show is true .

We pass in the ref to the div to assign it the ref.

Then we pass in that ref to th useRootClose hook to let us remove the container by setting show to false with the handleRootClose function.

We set the disabled property to make it disabled when show is false .

Conclusion

We can add the Portal component to let us add elements to wherever we want in the DOM.

The useRootClose hook lets us remove components whenever we click outside it.

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.