Lazy Popover

Lazy loading Popover using React.lazy and React.useTransition to avoid downloading additional code until the user interacts with the button.

import * as Ariakit from "@ariakit/react";
import { lazy, useState, useTransition } from "react";
import { Spinner } from "./spinner.tsx";
import "./style.css";
import { usePerceptibleValue } from "./use-perceptible-value.ts";
const Popover = lazy(() => import("./popover.ts"));
export default function Example() {
const [open, setOpen] = useState(false);
const [isPending, startTransition] = useTransition();
// Wait for 150ms before showing the spinner. Once the spinner is shown, it
// should be visible for enough time to avoid flickering.
const loading = usePerceptibleValue(isPending, {
delay: isPending ? 150 : 0,
return (
setOpen={(open) => {
if (open) {
return startTransition(() => setOpen(open));
<Ariakit.PopoverDisclosure className="button">
Accept invite
{loading ? <Spinner /> : <Ariakit.PopoverDisclosureArrow />}
{open && (
<Popover className="popover">
<Ariakit.PopoverArrow className="arrow" />
<Ariakit.PopoverHeading className="heading">
Team meeting
We are going to discuss what we have achieved on the project.
<p>12 Jan 2022 18:00 to 19:00</p>
<p>Alert 10 minutes before start</p>
<Ariakit.Button className="button">Accept</Ariakit.Button>

Controlling the popover state

You can control the open state of the popover by passing the open and setOpen props to the PopoverProvider component:

const [open, setOpen] = React.useState(false);
<PopoverProvider open={open} setOpen={setOpen}>

Learn more on the Component stores guide.

Stay tuned

Join 1,000+ subscribers and receive monthly tips & updates on new Ariakit content.

No spam. Unsubscribe anytime. Read latest issue