smart_popup
Independent, smooth, smart-positioning, sticky and floating vanilla JS tap, touch, click-interactivity overlay solution, all-in-one for Drupal 10, 11, 12 and above, to create a application-alike feel on additional information related to a part of the context. With extendable themes based on class names, optional flipping arrows, scroll behavior and with full Drupal use-ajax compatibility. Zero third-party libraries.
The goal is to have a suite of vanilla and independent modern Javascript behavior at hand to easily implement popup-alike modals, badges, info bubbles, tooltips and such into an existing Drupal project without disturbing Drupal's use-ajax system. Mainly with admin dashboards and shops in mind.
Features
- 6 themes:
default,soft,slate,bordered,elevated,sharp(all opaque, no gradients - varied by radius, border and shadow) - Optional flipping arrow anchored to the trigger
- Smart positioning - auto-picks the side with the most room
- Sticky to trigger on scroll - stays in viewport as long as possible, flips when the trigger leaves
- Reflows on resize / viewport change (uses
ResizeObserverwhen available) - Closes only on: outside click
Escapekey, the in-popup button - Preserves
use-ajax-Drupal.attachBehaviorsis called on popup content; existing AJAX, forms and behaviors keep working inside the popup - No HTML strings in JS - all popup DOM is built with
document.createElement - No third-party libraries - vanilla JS only
Install
- Copy the
smart_popup/folder intoweb/modules/contrib/. - Enable the module:
drush en smart_popup(or via/admin/modules). - Or use
composer require drupal/smart_popupanddrush en smart_popup
How it works (3 pieces)
- A hidden source element: any DOM node with an
id. A<template>is recommended. But can be<div><span>, you name it. - A trigger element - anything with
data-smart-popup-trigger="source-id". - The library -
smart_popup/smart_popupattached to the page.
That's it. Click the trigger and the smart popup is built from the source, positioned next to the trigger, and stays near the trigger, where ever you scroll and will close only on click or tap outside, or by pressing "Escape", or by clicking the close button.
Required attribute
Attribute Purposedata-smart-popup-trigger
ID of the source element to clone into the popup
Optional attributes
Attribute Values Defaultdata-smart-popup-placement
auto, top, bottom, left, right
auto
data-smart-popup-arrow
1, 0
1
Theme classes (on the trigger)
smart-popup--theme-default - smart-popup--theme-soft - smart-popup--theme-slate - smart-popup--theme-bordered - smart-popup--theme-elevated - smart-popup--theme-sharp
Usage
A. Twig (in a template, block, or node body)
{{ attach_library('smart_popup/smart_popup') }} <button type="button" class="smart-popup-trigger smart-popup--theme-bordered smart-popup--has-arrow" data-smart-popup-trigger="sp-source-hello" data-smart-popup-placement="auto" data-smart-popup-arrow="1"> Show details </button> <template id="sp-source-hello" class="smart-popup-source"> <h3>Hello from Smart Popup</h3> <p>Any markup goes here - including <a href="/node/1" class="use-ajax">use-ajax links</a>.</p> </template>
B. Render array (controller, block, preprocess)
$build['trigger'] = [
'#theme' => 'smart_popup_trigger',
'#label' => $this->t('More info'),
'#target_id' => 'sp-source-info',
'#theme_class' => 'smart-popup--theme-slate',
'#arrow' => TRUE,
'#placement' => 'auto',
'#trigger_tag' => 'button',
];
$build['source'] = [
'#theme' => 'smart_popup_content',
'#id' => 'sp-source-info',
'#content' => ['#markup' => '<p>Hello!</p>'],
];
$build['#attached']['library'][] = 'smart_popup/smart_popup';
C. Views
- Add a Custom text field with the
<template>source. - Add another Custom text field with the trigger markup pointing at the same id.
- In the view's Advanced ? CSS class or via a preprocess hook, attach
smart_popup/smart_popup.
D. Content (CKEditor)
If your text format allows the attributes and <template> tag, you can paste the markup directly. Make sure smart_popup/smart_popup is attached on the page (e.g. via a block, or globally in your theme's *.libraries.yml).
use-ajax compatibility
When a popup opens, the module calls:
Drupal.attachBehaviors(popupElement, drupalSettings);
so every Drupal behavior - use-ajax, ajax forms, tooltips, custom behaviors - is attached to the popup content. On close, Drupal.detachBehaviors(popupElement, drupalSettings, 'unload') is called. No existing use-ajax behavior on the page is disabled or replaced.
Public JS API
Drupal build (window.Drupal.smartPopup):
Drupal.smartPopup.open(triggerElement);
Drupal.smartPopup.closeAll();
Drupal.smartPopup.reposition();
Standalone build (window.SmartPopup):
SmartPopup.init(); // re-scan after DOM changes
SmartPopup.open(triggerEl); // open programmatically
SmartPopup.closeAll();
SmartPopup.reposition();
SmartPopup.onOpen = (contentEl, entry) => { /* hook */ };
Demo
- Open
demo.htmlinside module folder in a browser for a live, framework-free demonstration. - Or go to http://smart-popup.dev
License
GPLv3 - see LICENSE.md.