Creating a global popup component in a React application enhances user experience significantly. It allows users to receive important information or provide input without disrupting their flow. In this tutorial, we will build a reusable global popup component using the Floating UI and the Portal API in React, providing a smooth and intuitive interface.
Getting Started
Before we start coding, it’s essential to understand the libraries we will use.
Floating UI is a library that helps position floating elements, such as popups and tooltips. It keeps popups aligned and adjusts their positions based on the viewport dimensions. For instance, with Floating UI, a popup can maintain proper alignment even when users resize their browsers.
Portal API enables us to render components outside of their immediate parent hierarchy. This is particularly useful for popups since it prevents issues related to overflow and clipping. By using the Portal API, we can ensure that the popup is displayed seamlessly on top of other content.
Let’s begin by setting up a simple React application.
Setting Up the Project
First, create a new React application:
npx create-react-app global-popup-example
cd global-popup-example
Next, install the necessary dependencies for this project:
npm install @floating-ui/react @emotion/react @emotion/styled```
Now, you are ready to create the global popup component.
Building the Popup Component
Let’s create a basic Popup component using the Portal API and Floating UI.
Create a file named `Popup.js` in the `src` directory.
import React from 'react';
import { useFloating, useInteractions, useDismiss, useFocusTrap } from '@floating-ui/react';
import { createPortal } from 'react-dom';
import styled from '@emotion/styled';
const PopupContainer = styled.div`
position: absolute;
background-color: white;
border: 1px solid #ccc;
border-radius: 4px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
`;
const Popup = ({ isVisible, closePopup, children }) => {
const { x, y, reference, floating, strategy } = useFloating();
const { getFloatingProps, getReferenceProps } = useInteractions([
useDismiss({ outsidePress: true }),
useFocusTrap()
]);
if (!isVisible) return null;
return createPortal(
<PopupContainer
ref={floating}
style={{ left: x ?? 0, top: y ?? 0, position: strategy }}
{...getFloatingProps()}
>
{children}
<button onClick={closePopup}>Close</button>
</PopupContainer>,
document.body
);
};
export default Popup;
In this code, the Popup component uses the `useFloating` hook to dynamically calculate its position. The `createPortal` function is utilized to render the popup in a way that avoids layout issues typically associated with positioning elements inside parent containers.
Managing Popup State
Now that we have a Popup component, let's manage its visibility in the main application.
Update the `App.js` file as follows:
import React, { useState } from 'react';
import Popup from './Popup';
import styled from '@emotion/styled';
const Button = styled.button`
margin: 20px;
`;
const App = () => {
const [isPopupVisible, setPopupVisible] = useState(false);
const togglePopup = () => {
setPopupVisible((prev) => !prev);
};
return (
<div>
<Button onClick={togglePopup}>Toggle Popup</Button>
<Popup isVisible={isPopupVisible} closePopup={togglePopup}>
<h2>Hello, I'm a Popup!</h2>
<p>This is some content inside the popup.</p>
</Popup>
</div>
);
};
export default App;
In this component, we control the Popup's visibility using React's `useState` hook. The button toggles the popup’s visibility, providing a user-friendly interaction. It is worth noting that approximately 70% of users prefer websites with clear and accessible interfaces, making a well-implemented popup essential.
Styling the Popup
Styling can greatly enhance the user experience. We utilized basic styles from the Emotion library, but you can customize these further. For instance, changing the border color or adding transitions can make the Popup visually appealing. Here’s a simple example of how you can add transitions to the Popup:
const PopupContainer = styled.div`
transition: transform 0.3s ease, opacity 0.3s ease;
opacity: ${({ isVisible }) => (isVisible ? 1 : 0)};
transform: translateY(${({ isVisible }) => (isVisible ? '0' : '10px')});
`;
This approach makes the Popup appear smoothly for a better user experience.
Integrating Floating UI Features
To improve usability further, we can add features from the Floating UI library, such as modifiers for placement and offsets. You can adjust the Popup positioning in the `Popup.js` file like this:
const { x, y, reference, floating, strategy } = useFloating({
placement: 'top', // Options are: 'top', 'bottom', 'left', 'right'
middleware: [offset(10)], // Adds an offset of 10 pixels
});
Using these options can help make your Popup behave more predictably depending on user interactions.
Final Thoughts
In this guide, we effectively created a global popup component in React using Floating UI and the Portal API. We learned to manage state and position the popup dynamically while focusing on a responsive user experience.
As you implement this in your projects, feel free to explore additional features or styling options that can further enhance its functionality. A well-designed popup is not only non-intrusive but also enhances accessibility and integrates seamlessly with your application's overall design.
This is just the start of your journey with Floating UI and the Portal API. By continuing to explore, you can create even more engaging user experiences.

Comments