How to Create Nested and Auto-dismissable Layers in React

Context and hook to add support for nested, auto-dismissable layers. State can be globally controlled through context. Best used with react-popper.

npm i react-dismissable-layers
yarn add react-dismissable-layers

Demo

Check out the Storybook Demo to see in action.

Screen Shot 2021-07-07 at 8 35 04 AM

Quick Start

Add <DismissableLayersGlobalProvider> on a parent component. Use the useDismissable() hook to associate different toggleable components.

import { useDismissable } from 'react-dismissable-layers';

// open and close
const Component = () => {
  const [open, toggleOpen] = useDismissable(false);

  return (
    <div>
      <button onClick={toggleOpen}>Open Tooltip</button>
      {open && <Popper>Tooltip Content</Popper>}
    </div>
  );
};
import { DismissableLayerContext } from 'react-dismissable-layers';

// close all dismissibles in context
const OtherComponent = () => {
  const dismissOverlay = React.useContext(DismissableLayerContext);

  const close = React.useCallback(() => {
    dismissOverlay.dismissAllGlobally();
  }, []);

  return <button onClick={close}>Close All</button>;
};

API

DismissableLayersGlobalProvider - global provider for Dismissable Layers, wrap the whole app to make sure the useDismissable hook works with layers.

interface DismissableLayersGlobalProviderProps {
  /**
   * optional prop, the HTML-node to listen close events, default is `document`
   */
  rootNode?: HTMLElement | Document;
}

const DismissableLayersGlobalProvider = React.FC<DismissableLayersGlobalProviderProps>;


 

useDismissable - a hook to toggle and dismiss poppers.

interface Options {
  /**
   * ref for the popper content, to not close on the content's [dismissEvent] action
   */
  ref?: RefObject<Element>;

  /**
   * callback which will be invoked when the popper is closed
   */
  onClose?: null | VoidFunction;

  /**
   * event on which popper will be closed, default is `'click'`
   */
  dismissEvent?: DismissEventType;

  /**
   * the popper will be closed just by the [dismissEvent] action, without any layers logic, default is `false`
   */
  disableLayers?: boolean;

  /**
   * do not close on default prevented events, default is `true`
   */
  skipDefaultPrevented?: boolean;
}

type Api = readonly [
  isOpened: boolean,

  /**
   * function to toggle popper
   */
  toggle: VoidFunction,

  /**
   * function to force close popper
   */
  close: VoidFunction
];

const useDismissable = (defaultValue = false, options: Options = {}) => Api;


 

DismissableLayerContext - a context to read a dissmissable layer, in most cases shouldn't be used in app layer.

interface DismissableLayerValue<T extends HTMLElement | Document = Document> {
  /**
   * for internal usage only
   */
  readonly _subscriber: Subscriber;

  /**
   * root node of the dismiss layer
   */
  readonly rootNode: T;

  /**
   * dismiss currently opened in the current layer
   */
  readonly dismiss: VoidFunction;

  /**
   * has handler on the current layer
   */
  readonly hasHandler: () => boolean;

  /**
   * add close handler to the current layer
   */
  readonly addHandler: (eventType: DismissEventType, handler: DismissEventHandler) => void;

  /**
   * remove close handler from the current layer
   */
  readonly removeHandler: (eventType: DismissEventType) => void;

  /**
   * dismiss all on all layers
   */
  readonly dismissAllGlobally: VoidFunction;

  /**
   * has subscriber on any layer
   */
  readonly hasHandlersGlobally: () => boolean;
}

const DismissableLayersGlobalProvider = React.FC<DismissableLayersGlobalProviderProps>;


 

DismissableLayerProvider - provider for Dismissable Layer, wrap the popper content to make the nested poppers works as a nested ones.

interface DismissableLayerProviderProps {
  /**
   * optional prop, the HTML-node to listen close events, default is `document`
   */
  rootNode?: HTMLElement | Document;
}

const DismissableLayerProvider = React.FC<DismissableLayerProviderProps>;

View on GitHub: https://github.com/voiceflow/react-dismissable-layers 

#react #javascript 

How to Create Nested and Auto-dismissable Layers in React
7.45 GEEK