Agents (llms.txt)
Octocat

useTopLayer

A hook to push an element to the application's Top Layer

Source Code

import { type RefCallback, useCallback, useRef } from 'react';

type PopoverType = 'manual' | 'hint';

const showAsPopover = <T extends HTMLElement>(
  element: T,
  type: PopoverType
) => {
  element.setAttribute('popover', type);
  try {
    element.showPopover();
  } catch {
    // already showing — ignored
  }
};

const hideAsPopover = <T extends HTMLElement>(element: T) => {
  try {
    element.hidePopover();
  } catch {
    // already hidden / not connected — ignored
  }
  element.removeAttribute('popover');
};

/**
 * Custom hook to push an element to the application's Top Layer.
 *
 * `type` controls the popover semantics:
 * - `manual` (default): independent popover that stays open until closed.
 * - `hint`: tooltip-style popover that always stacks above other popovers
 *   without dismissing them. Use this for tooltips so they float above an
 *   already-open `popover="manual"` (e.g. an open dropdown panel).
 *
 * Returns a callback ref. We intentionally don't use `useLayoutEffect`
 * because some floating-ui consumers (notably `<FloatingPortal>`) don't have
 * their target element in the DOM on the first render — the portal node is
 * created in an effect, the element mounts on the *second* render, and a
 * layout effect would have already fired by then with a null ref. A callback
 * ref activates the moment the element attaches, regardless of how many
 * render passes the consumer's wrappers take.
 *
 * If you also need imperative access to the element, compose this ref with
 * your own `useRef` via `composeRefs`.
 *
 *  @example
 * ```tsx
 * const ref = useTopLayer<HTMLDivElement>(isActive);
 * return <div ref={ref}>Top Layer Content</div>;
 * ```
 */
export const useTopLayer = <T extends HTMLElement>(
  active: boolean = true,
  type: PopoverType = 'manual'
): RefCallback<T> => {
  const previousRef = useRef<T | null>(null);

  return useCallback(
    (element: T | null) => {
      const previous = previousRef.current;
      if (previous && previous !== element) hideAsPopover(previous);

      previousRef.current = element;

      if (element && active) showAsPopover(element, type);
    },
    [active, type]
  );
};

Features

  • Top Layer Positioning - Elevates elements to the browser’s Top Layer for guaranteed z-index supremacy
  • HTML Popover API - Uses the native HTML popover API for optimal performance and accessibility
  • Conditional Activation - Supports conditional activation/deactivation through the active parameter

API Reference

Prop Default Type Description
active - boolean Whether the element should be pushed to the Top Layer. Defaults to true.
type - "manual" | "hint" Popover semantics. `manual` (default) is an independent popover that stays open until closed. `hint` is a tooltip-style popover that always stacks above other popovers without dismissing them — use it for tooltips that should float above an already-open `popover="manual"` (e.g. an open dropdown panel).

The hook returns a RefCallback<T> that should be attached to the target HTML element. If you also need imperative access to the element, compose this ref with your own useRef via composeRefs.

Examples

Basic Usage


          const Component = () => {
  const ref = useTopLayer<HTMLDivElement>();

  return (
    <div ref={ref} className="rounded border bg-white p-4 shadow">
      This element is now in the Top Layer!
    </div>
  );
};
        

Conditional Top Layer


          const Component = ({ isOpen }) => {
  const ref = useTopLayer<HTMLDivElement>(isOpen);

  return (
    <div ref={ref} className={cn("bg-opacity-50 fixed inset-0 bg-black", isOpen ? "block" : "hidden")}>
      <div className="flex h-full items-center justify-center">
        <div className="rounded-lg bg-white p-6 shadow-xl">
          <h2>Modal Content</h2>
          <p>This modal is in the Top Layer when open.</p>
        </div>
      </div>
    </div>
  );
};
        

Further Reading

For a deeper dive into the browser’s Top Layer and how it works under the hood, check out the MDN Web Docs on the Top Layer.

Previous

useTicker

Next

Setup