cue

Getting started

Create a Cue environment and open your first overlay.

Cue starts with one local instance. Create it once, mount its provider, and define overlays from that instance.

Install

npm i @vlkoss/cue

If you use shadcn, use the Using Cue with shadcn setup instead.

Create a Cue

Start with the smallest possible configuration:

// components/cue.ts
"use client";

import { createCue } from "@vlkoss/cue";

export const cue = createCue();

You now have the Cue instance used to define and open your overlays.

Mount the provider

Mount the provider for that same Cue instance near the root of the app:

import { cue } from "./components/cue";

export function App() {
  return (
    <cue.OverlayProvider>
      <Page />
    </cue.OverlayProvider>
  );
}

Define an overlay

The first callback argument contains only values passed to open() or openAsync(). Cue runtime values live in the second argument.

import { cue } from "./components/cue";

export const welcome = cue.createOverlay<{ message: string }>((props, ctx) => (
  <div role="dialog" aria-hidden={!ctx.open}>
    <p>{props.message}</p>
    <button type="button" onClick={() => ctx.close()}>
      Close
    </button>
  </div>
));

Open it from an event handler, effect, or any other client-side code:

welcome.open({ message: "Hello from Cue" });

open() returns a close function for that instance. openAsync() returns a Promise that resolves when the instance closes.

Next.js

Put createCue() and the overlay definitions in a client-side module. A server layout can render the provider:

// app/layout.tsx
import { cue } from "@/components/cue";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        <cue.OverlayProvider>{children}</cue.OverlayProvider>
      </body>
    </html>
  );
}

createCue() and cue.createOverlay() do not use hooks, so client-side modules can call them at module scope.

On this page