npm.io
5.0.0 • Published yesterday

@preline/overlay

Licence
Licensed under MIT and Preline UI Fair Use License
Version
5.0.0
Deps
0
Size
160 kB
Vulns
0
Weekly
0
Stars
6.4K

Overlay

The Overlay Tailwind plugin is an unstyled JavaScript utility for creating modals, drawers, and more, enhancing user interaction and content layout.

npm License: MIT Demo

Contents

Overview

The Overlay component provides a flexible foundation for creating modals, drawers, sidebars, and other overlay-based UI elements. It handles backdrop management, focus trapping, keyboard navigation, and z-index stacking automatically.

Key Features:

  • Modal and drawer support
  • Automatic backdrop management
  • Focus trapping and keyboard navigation (Tab, Esc)
  • Z-index stacking for multiple overlays
  • Responsive breakpoint support
  • Auto-close on screen size changes
  • Programmatic control via JavaScript API
  • Event system for lifecycle hooks
  • Accessibility attributes (ARIA) built-in

Installation

To get started, install Overlay plugin via npm, else you can skip this step if you are already using Preline UI as a package.

npm i @preline/overlay
CSS

Use @source to register the plugin's JavaScript path for Tailwind CSS scanning, then @import the plugin's CSS files into your Tailwind CSS file.

@import "tailwindcss";

/* @preline/overlay */
@source "../node_modules/@preline/overlay/*.js";
@import "./node_modules/@preline/overlay/variants.css";
@import "./node_modules/@preline/overlay/theme.css";
JavaScript

Include the JavaScript that powers the interactive elements near the end of your </body> tag:

<script src="./node_modules/@preline/overlay/index.js"></script>
Manual Initialization

Use the non-auto entry if you need manual initialization. In this mode, automatic initialization on page load is not included, so the component should be initialized explicitly.

<script type="module">
  import HSOverlay from "@preline/overlay/non-auto.mjs";

  new HSOverlay(document.querySelector("#overlay"));
</script>
Via Bundler

When using a bundler (Vite, webpack, etc.), import the plugin directly as an ES module.

@preline/overlay is the auto-init entry: it scans the DOM and initializes matching elements automatically.

import "@preline/overlay";

@preline/overlay/non-auto is the manual entry: use it when you want explicit control over when initialization happens, either via autoInit() or by creating a specific instance yourself.

import HSOverlay from "@preline/overlay/non-auto";

HSOverlay.autoInit();

// Or initialize a specific element manually
const el = document.querySelector("#overlay");
if (el) new HSOverlay(el);
TypeScript

This package ships with TypeScript type definitions. No additional @types/ package is needed.

Basic usage

The following example demonstrates the minimal HTML structure required for an overlay component. This is a base template without custom styling - you can apply your own CSS classes and styles as needed. The overlay appears when the button is clicked.

<button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="hs-unstyled-modal" data-hs-overlay="#hs-unstyled-modal">
  Open modal
</button>

<div id="hs-unstyled-modal" class="hs-overlay hidden size-full fixed top-0 start-0 z-60 overflow-x-hidden overflow-y-auto pointer-events-none" role="dialog" tabindex="-1" aria-labelledby="hs-unstyled-modal-label">
  <div class="hs-overlay-open:opacity-100 hs-overlay-open:duration-500 opacity-0 transition-all sm:max-w-lg sm:w-full m-3 sm:mx-auto">
    <div class="pointer-events-auto">
      <h3 id="hs-unstyled-modal-label">Title</h3>
      Modal content
    </div>
  </div>
</div>

Structure Requirements:

  • data-hs-overlay: Required on the trigger button, must be a valid CSS selector pointing to the overlay element
  • hs-overlay: Required class on the overlay content container
  • hidden class on the overlay initially
  • Proper ARIA attributes (aria-haspopup, aria-expanded, aria-controls, role="dialog", aria-labelledby)

Initial State:

  • Set aria-expanded="false" on the trigger button initially
  • Add hidden class to the overlay initially
  • Overlay visibility is controlled by the plugin

Configuration Options

Data Attributes

Data attributes are added directly to HTML elements to configure overlay behavior.

Attribute Target Element Type Default Description
data-hs-overlay-options Trigger button object (JSON) - Defines the modal configuration. Should be added to the button (trigger).
:hiddenClass Inside data-hs-overlay-options string "hidden" Defines which classes will be added/removed when modal toggles.
:emulateScrollbarSpace Inside data-hs-overlay-options boolean false If true, then adds right padding to the body equal to the size of the scrollbar. Useful to prevent layout shift when overlay opens.
:isClosePrev Inside data-hs-overlay-options boolean true Determines whether the previous open modal will be closed when the next one is opened.
:backdropClasses Inside data-hs-overlay-options string "hs-overlay-backdrop transition duration fixed inset-0 bg-gray-900/50 dark:bg-neutral-900/80" Defines default backdrop classes.
:backdropExtraClasses Inside data-hs-overlay-options string - Allows to add additional classes besides those specified in backdropClasses.
:backdropParent Inside data-hs-overlay-options string - Allows to specify the selector of the element where the backdrop will be generated.
:moveOverlayToBody Inside data-hs-overlay-options number | null null Moves the overlay to the body tag if the screen width is less than the value specified.
:isToggleClassesImmediately Inside data-hs-overlay-options boolean false When set to true, toggles hidden, open, and opened classes immediately instead of waiting for the open delay, resize debounce, or close transition.
data-hs-overlay-backdrop-container Overlay content string (CSS selector) null Backdrop element selector. Should be added to the overlay (content).
data-hs-overlay-keyboard Overlay content boolean true When set to false, the modal will not close when pressing the ESC button on the keyboard. Should be added to the overlay (content).
CSS Classes (Modifiers)

CSS class modifiers use Tailwind-style syntax with -- prefix to control overlay behavior.

Class Modifier Target Element Values Default Description
[--overlay-backdrop:*] Overlay content "static" | null null When backdrop is set to "static", the modal will not close when clicking outside it. Should be added to the overlay (content).
[--auto-hide:*] Overlay content number 0 Milliseconds for auto-closing a modal. When set to 0, the modal will not close automatically. Should be added to the overlay (content).
[--auto-close:*] Overlay content 'sm' | 'md' | 'lg' | 'xl' | '2xl' | number null Screen resolution at which the overlay will close automatically. Should be added to the overlay (content).
[--auto-close-equality-type:*] Overlay content 'less-than' | null null This option determines the condition under which an overlay should automatically close based on the window's width. When set to less-than, the overlay will close if the window's width is less than or equal to the value defined in [--auto-close:*]. Otherwise the overlay will close if the window's width is greater than or equal to the [--auto-close:*] threshold. Should be added to the overlay (content).
[--opened:*] Overlay content 'sm' | 'md' | 'lg' | 'xl' | '2xl' | number null Screen resolution at which the plugin will apply functionality for the initially opened overlay. Should be added to the overlay (content).
[--body-scroll:*] Overlay content boolean true When set to false, the body scroll will be hidden as soon as the modal opens. Should be added to the overlay (content).
[--tab-accessibility-limited:*] Overlay content "true" | "false" "true" Restricts focus to elements within an overlay (or modal). Should be added to the overlay (content).
[--has-autofocus:*] Overlay content "true" | "false" "true" Disables autofocus on the first focusable element when opening an overlay. Should be added to the overlay (content).
[--has-dynamic-z-index:*] Overlay content "true" | "false" "false" When set to "true", each newly opened element in the group will receive an incremented z-index inline, ensuring it appears above previously opened elements with the same base z-index. Should be added to the overlay (content).
[--is-layout-affect:*] Overlay content "true" | "false" "false" Informs the plugin that the instance affects the website layout. Should be added to the overlay (content).
[--toggle-classes-immediately:*] Overlay content "true" | "false" "false" When set to "true", toggles hidden, open, and opened classes immediately instead of waiting for the open delay, resize debounce, or close transition.

Example:

<div class="hs-overlay --overlay-backdrop:static --auto-hide:5000">
  <!-- Overlay content -->
</div>
Required CSS Classes

These classes define the structure and must be present for the overlay to function.

Class Required On Purpose
hs-overlay Overlay content container Identifies the overlay content element
Optional CSS Classes
Class Required On Purpose
hs-overlay-animation-target Element inside overlay Defines an element inside the popup, after the end of whose animation the popup will be completely hidden. Has no parameters.
autofocus Input element inside overlay Focus the first input in a modal with the autofocus attribute on opening. Must be added to an input element inside a modal window.
Tailwind Modifiers
Name Description
hs-overlay-open:* Defines classes that will be applied to any elements inside the hs-overlay when the overlay is open.
hs-overlay-backdrop-open:* Defines classes that will be applied to backdrop when the overlay is open.
hs-overlay-layout-open:* Defines classes that will be applied to any elements inside the body tag when the overlay is open.

JavaScript API

The HSOverlay object is available in the global window object after the plugin is loaded.

Instance Methods

These methods are called on an overlay instance.

Method Parameters Return Type Description
open(cb) cb: Function | null (optional) Promise<void> Forces the overlay to open programmatically. Optionally accepts a callback function that will be called after opening. Returns a Promise.
close(forceClose, cb) forceClose: boolean (optional)
cb: Function | null (optional)
Promise<unknown> Forces the overlay to close programmatically. forceClose bypasses animations and closes immediately. Optionally accepts a callback function. Returns a Promise.
minify(isMinified, cb) isMinified: boolean
cb: Function | null (optional)
void Minimizes or restores the overlay. Useful for drawer/sidebar components.
updateToggles() None void Updates the toggle buttons. Useful after dynamically adding or removing toggle buttons.
destroy() None void Destroys the overlay instance, removes all generated markup, classes, and event listeners. Use when removing overlay from DOM.
Static Methods

These methods are called directly on the HSOverlay class.

Method Parameters Return Type Description
HSOverlay.getInstance(target, isInstance) target: HTMLElement | string (CSS selector)
isInstance: boolean (optional)
HTMLElement | { id: string | number, element: HSOverlay } | null Returns the overlay instance or element associated with the target. If isInstance is true, returns collection item object { id, element } where element is the HSOverlay instance. If isInstance is false or omitted, returns the DOM element (HTMLElement). Returns null if overlay instance is not found.
HSOverlay.open(target) target: HSOverlay | HTMLElement | string (CSS selector) void Opens the overlay identified by target. Accepts an overlay instance, DOM element, or CSS selector string. Static alternative to instance open() method.
HSOverlay.close(target) target: HSOverlay | HTMLElement | string (CSS selector) void Closes the overlay identified by target. Accepts an overlay instance, DOM element, or CSS selector string. Static alternative to instance close() method.
Usage Examples

Example 1: Using instance methods (public API)

// Create a new overlay instance
const modal = new HSOverlay(document.querySelector('#hs-modal'));
const openBtn = document.querySelector('#hs-open-btn');

// Open overlay programmatically
openBtn.addEventListener('click', () => {
  modal.open();
});

Example 2: Using static methods

const openBtn = document.querySelector('#hs-open-btn');

// Open overlay using static method (no instance needed)
openBtn.addEventListener('click', () => {
  HSOverlay.open('#hs-modal');
});

Example 3: Getting instance and using methods (recommended pattern)

// Get the overlay instance
const instance = HSOverlay.getInstance('#hs-modal', true);

if (instance) {
  const { element } = instance; // element is the HSOverlay instance
  const openBtn = document.querySelector('#hs-open-btn');
  const closeBtn = document.querySelector('#hs-close-btn');

  // Use instance methods
  openBtn.addEventListener('click', () => {
    element.open();
  });

  closeBtn.addEventListener('click', () => {
    element.close();
  });

  // Clean up when removing from DOM
  function removeOverlay() {
    element.destroy();
  }
}

Example 4: Destroying overlay instance

const instance = HSOverlay.getInstance('#hs-modal', true);

if (instance) {
  const { element } = instance;
  const removeBtn = document.querySelector('#hs-remove-btn');

  removeBtn.addEventListener('click', () => {
    // Clean up before removing from DOM
    element.destroy();
    // Now safe to remove the element
    document.querySelector('#hs-modal').remove();
  });
}

Events

Overlay instances emit events that can be listened to for lifecycle hooks and custom behavior.

Event Name When Fired Callback Parameter Description
on:open After overlay is opened HSOverlay (overlay instance) Fires after the overlay has been displayed. Use for post-open actions like loading content or focusing elements.
on:close After overlay is closed HSOverlay (overlay instance) Fires after the overlay has been hidden. Use for cleanup or state updates.
Event Usage Example
// Get overlay instance
const instance = HSOverlay.getInstance('#hs-modal', true);

if (instance) {
  const { element } = instance;

  // Listen to open event
  element.on('open', (overlayInstance) => {
    console.log('Overlay opened:', overlayInstance);
    // Perform actions after overlay opens
    // e.g., load content, focus input, track analytics
  });

  // Listen to close event
  element.on('close', (overlayInstance) => {
    console.log('Overlay closed:', overlayInstance);
    // Perform cleanup or state updates
  });
}

Common Patterns

Pattern 1: Static Backdrop

Prevent closing when clicking outside the overlay.

<div class="hs-overlay --overlay-backdrop:static">
  <!-- Overlay content -->
</div>
Pattern 2: Auto-close on Screen Size

Close overlay automatically at specific breakpoints.

<div class="hs-overlay --auto-close:md --auto-close-equality-type:less-than">
  <!-- Overlay content -->
</div>
Pattern 3: Programmatic Control

Control overlay from external buttons.

<button id="hs-open-modal">Open Modal</button>
<button id="hs-close-modal">Close Modal</button>

<div id="hs-modal-first" class="hs-overlay hidden">
  <!-- Overlay content -->
</div>

<script>
  const instance = HSOverlay.getInstance('#hs-modal-first', true);
  
  if (instance) {
    const { element } = instance;

    document.querySelector('#hs-open-modal').addEventListener('click', () => {
      element.open();
    });

    document.querySelector('#hs-close-modal').addEventListener('click', () => {
      element.close();
    });
  }
</script>

License

Copyright (c) 2024 Htmlstream.

Licensed under the MIT License.

Keywords