npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

top-layer

v2.0.1

Published

Library for working with native HTML dialogs and upper layers (f.e. notifications) without unnecessary application rerenders.

Downloads

29

Readme

top-layer

Read the documentation at nimpl.dev/docs/top-layer

Top Layer is a Library for working with native HTML dialogs and upper layers (f.e. notifications) without unnecessary application rerenders.

The library allows you to manage dialogs and custom elements in the browser Top Layer. This layer is supported by all modern browsers. It includes a Dialogs API and a Toasts API.

[!TIP] The native Toasts API doesn't behave correctly on top of the Dialogs API; use an upper layer for this instead.

Installation

npm i top-layer

Configuration

Wrap your application in the provider:

import { TopLayerProvider } from "top-layer";

import { ShareDialog } from "@src/components/share-dialog";
import { FullViewDialog } from "@src/components/full-view-dialog";
import { ToastLayer } from "@src/components/toast-layer";

const RootLayout: React.FC<{ children: React.ReactNode }> = ({ children }) => (
  <TopLayerProvider
    dialogs={[
      { dialog: ShareDialog, id: "share" },
      { dialog: FullViewDialog, id: "full-view" },
    ]}
    upperLayers={[{ layer: ToastLayer, id: "toast" }]}
  >
    {children}
  </TopLayerProvider>
);

export default RootLayout;

[!NOTE] TopLayerProvider never causes rerenders, so it is recommended to use it over the entire application.

Usage

The library provides an interface for working with dialogs and upper layers like toasts. You can use them together or separately, in any order.

Dialogs

This is not a UI library; you create the dialog-content components and register them with the provider. The provider renders native dialog elements for you (and only it).

Example of a basic dialog-content component:

"use client";

import { useDialogAction, useDialogData } from "top-layer/dialogs/hooks";

export const AlertDialog: React.FC = () => {
  const { close } = useDialogAction();
  const message = useDialogData<string>();

  return (
    <div className="relative m-auto p-16 bg-slate-900 rounded-2xl w-full max-w-5xl z-10">
      <p>{message}</p>
      <button onClick={() => close()}>Close</button>
    </div>
  );
};

Register it in the provider and optionally pass props to the underlying html dialog:

<TopLayerProvider
  dialogs={[
    {
      dialog: AlertDialog,
      id: "alert",
      props: { id: "alert-dialog" },
    },
  ]}
/>

Open the dialog from anywhere:

import { useDialogAction } from "top-layer/dialogs/hooks";
// ...
const { open } = useDialogAction({ id: "alert" });
// ...
<button onClick={() => open({ data: "Base Alert Dialog" })}>
  Open Alert Dialog
</button>;

[!NOTE] If you need to control dialogs outside React (e.g., Redux-Saga), use the standalone functions openDialog and closeDialog.

Upper Layers

Upper layers are React components rendered above the app root and inside each dialog (so they can appear above dialog content). Examples include toasts, global spinners, and banners.

Example of base upper-layer component:

"use client";

import {
  useUpperLayerData,
  useUpperLayerStore,
} from "top-layer/upper-layers/hooks";

type ToastData =
  | { message: string; type: "success" | "warning" | "error" | "neutral" }
  | undefined;

export const ToastLayer: React.FC = () => {
  const data = useUpperLayerData<ToastData>();
  const { reset } = useUpperLayerStore();

  if (!data) return null;

  return (
    <div className={`toast toast_${data.type}`} onClick={() => reset()}>
      {" "}
      {data.message}{" "}
    </div>
  );
};

Update layer data from anywhere in React:

import { useUpperLayerStore } from "top-layer/upper-layers/hooks";
// ...
const { update } = useUpperLayerStore({ id: "toast" });
// ...
<button onClick={() => update({ data: { message: "Saved", type: "success" } })}>
  Show Toast
</button>;

Or from outside React using utilities:

import {
  updateUpperLayerData,
  resetUpperLayerData,
} from "top-layer/upper-layers/utils";

updateUpperLayerData("toast", { message: "Failed", type: "error" });
// ...
resetUpperLayerData("toast");

API

TopLayerProvider

Main package provider. It must be added above the part of the application where you plan to use dialogs and upper layers.

[!TIP] TopLayerProvider never causes re-renders, so it is recommended to install it over the entire application.

import { TopLayerProvider } from "top-layer";

import { ShareDialog } from "@src/components/share-dialog";
import { FullViewDialog } from "@src/components/full-view-dialog";
import { ToastLayer } from "@src/components/toast-layer";

const RootLayout: React.FC<{ children: React.ReactNode }> = ({ children }) => (
  <TopLayerProvider
    dialogs={[
      { dialog: ShareDialog, id: "share" },
      { dialog: FullViewDialog, id: "full-view" },
    ]}
    upperLayers={[{ layer: ToastLayer, id: "toast" }]}
  >
    {children}
  </TopLayerProvider>
);

export default RootLayout;

Props

dialogs - Array of dialogs with keys:

  • dialog - dialog-content component;

  • id - id of the dialog to control it from anywhere;

  • props - props passed to the underlying native dialog element (optional);

  • defaultData - initial data available via hooks (optional).

upperLayers - Array of upper layers with keys:

  • layer - upper-layer component;

  • id - id of the upper layer to control it from anywhere;

  • defaultData - initial data available via hooks (optional).

Dialogs API

Hooks for dialog control and state inside registered dialog content.

useDialogAction

import { useDialogAction } from "top-layer/dialogs/hooks";
// ...
const { open, close } = useDialogAction({ id: "modal" });
// ...
<button onClick={() => open({ data: { title: "Some modal title" } })}>Show Modal</button>
// ...
<button onClick={() => close()}>Close Modal</button>

Arguments

id - dialog id (optional if used inside the dialog-content component, where it is provided by context).

Returns

open - open dialog. Arguments: { data?: unknown; id?: string }.

close - close dialog. Arguments: { data?: unknown; id?: string }.

useDialogData

Hook to read reactive data passed to a dialog.

import { useDialogData } from "top-layer/dialogs/hooks";
const data = useDialogData<{ title: string }>();

Arguments

id - dialog id (optional if used inside the dialog-content component, where it is provided by context).

openDialog

Standalone function to open dialogs outside React.

import { openDialog } from "top-layer/dialogs/utils";
openDialog("alert", { title: "Some Alert Message" });

closeDialog

Standalone function to close dialogs outside React.

import { closeDialog } from "top-layer/dialogs/utils";
closeDialog("modal");

Upper Layers API

Hooks and utilities to manage arbitrary upper-layer components.

useUpperLayerStore

import { useUpperLayerStore } from "top-layer/upper-layers/hooks";
const { update, reset, get, subscribe, unsubscribe } = useUpperLayerStore({
  id: "toast",
});

Arguments

id - layer id (optional if used inside the layer-content component, where it is provided by context).

useUpperLayerData

import { useUpperLayerData } from "top-layer/upper-layers/hooks";
const data = useUpperLayerData<{ message: string; type: string }>();

Arguments

id - layer id (optional if used inside the layer-content component, where it is provided by context).

updateUpperLayerData / resetUpperLayerData

Standalone functions to update or reset upper-layer data outside React.

import {
  updateUpperLayerData,
  resetUpperLayerData,
} from "top-layer/upper-layers/utils";
updateUpperLayerData("toast", { message: "Saved", type: "success" });
resetUpperLayerData("toast");

Additional

Please consider giving a star if you like it, this motivates the author to continue working on this and other solutions ❤️

Create issues with wishes, ideas, difficulties, etc. All of them will definitely be considered and thought over.

License

MIT