BBC's guide to development
  • General

    • About
    • Tools
    • Git(hub)
    • Showpad
    • Hosting
    • Maintenance
    • Security
    • Go live checklist
  • Front-end development

    • Bundlers
    • CSS/SCSS
    • Javascript
    • Vue
    • PHP
    • Mails
    • Dev Faq
  • Functions
  • Mixins
  • General

    • OOP Structure
  • Component Classes

    • Accordion
    • App
    • Component
    • HighwayApp
    • Popup
    • PNG Sequencer
    • Tab
  • Manager Classes

    • BountListenerMgr
    • Cache
    • Configuration
    • InViewStateMgr
    • Instance Manager
    • Event dispatcher
  • Factories

    • SwiperFactory
  • PDF

    • AssetLoader
    • BasePdfDoc
    • TemplatePdfDoc
    • CustomPdfDoc
  • Utility functions

    • canvas
    • Connection Status
    • css
    • dev
    • placeholder
    • dom
    • fetch
    • json
    • object
    • scroll
    • scrollbar
    • spreadsheets
    • string
    • url
  • General

    • ComponentMgr
    • ThreeJsViewer
  • Components

    • ComponentMgr
    • GltfModel
    • Snappable
    • Socket
    • ThreeJsViewer
    • ThreeJsViewerCamera
  • Loaders

    • ConfigurationSerializer
    • GltfBlockParser
  • Utils

    • CanvasInputAdapter
    • CollisionManager
    • SocketGridExpander
    • blender
    • headless
  • General

    • Troubleshooting
    • Legacy
  • Components

    • AssetBar
    • ConfigGenerator
    • ShowpadApp
  • Managers

    • Assets
    • AppsDb
    • Config
  • Utils

    • Connection Status
    • general
    • showpad-interactive
    • showpad-upload
  • Components

    • Accordion
    • BackButton
    • Breadcrumb
    • ByltButton
    • Hamburger
    • Icon
    • Logo
    • Loader
    • Modal
    • Popup
    • Prompt
    • ProgressBar
    • TextLoader
  • Composables

    • useDebugMode
    • useConnectionStatus
  • Utils

    • dom
    • props
  • General

    • General
    • Tracking
  • Components

    • Accordion
    • ActionButton
    • AssetItem
    • AssetList
    • BackButton
    • ConfigGenButton
    • Logo
    • Media
    • Modal
    • Popup
    • Prompt
    • SPButton
    • SPRouterView
    • SPTrackedRouterLink
    • TextLoader
    • View
  • Composables

    • useConnectionStatus
  • Stores

    • useAppsDbStore
    • useBreadcrumbStore
    • useShowpadAPIStore
    • useShowpadSDKStore
    • useSpConfigStore
    • useSpStore
    • useSpTrackingStore
  • The New Kit

    • General
    • Installation & Usage
    • ACF Blocks
    • PHPCS
    • Functions
    • Vite
    • WP Config
    • Staging Deployment
  • Best Practices

    • Page Structure
    • Fonts/Typography
  • Todo
GitHub
  • General

    • About
    • Tools
    • Git(hub)
    • Showpad
    • Hosting
    • Maintenance
    • Security
    • Go live checklist
  • Front-end development

    • Bundlers
    • CSS/SCSS
    • Javascript
    • Vue
    • PHP
    • Mails
    • Dev Faq
  • Functions
  • Mixins
  • General

    • OOP Structure
  • Component Classes

    • Accordion
    • App
    • Component
    • HighwayApp
    • Popup
    • PNG Sequencer
    • Tab
  • Manager Classes

    • BountListenerMgr
    • Cache
    • Configuration
    • InViewStateMgr
    • Instance Manager
    • Event dispatcher
  • Factories

    • SwiperFactory
  • PDF

    • AssetLoader
    • BasePdfDoc
    • TemplatePdfDoc
    • CustomPdfDoc
  • Utility functions

    • canvas
    • Connection Status
    • css
    • dev
    • placeholder
    • dom
    • fetch
    • json
    • object
    • scroll
    • scrollbar
    • spreadsheets
    • string
    • url
  • General

    • ComponentMgr
    • ThreeJsViewer
  • Components

    • ComponentMgr
    • GltfModel
    • Snappable
    • Socket
    • ThreeJsViewer
    • ThreeJsViewerCamera
  • Loaders

    • ConfigurationSerializer
    • GltfBlockParser
  • Utils

    • CanvasInputAdapter
    • CollisionManager
    • SocketGridExpander
    • blender
    • headless
  • General

    • Troubleshooting
    • Legacy
  • Components

    • AssetBar
    • ConfigGenerator
    • ShowpadApp
  • Managers

    • Assets
    • AppsDb
    • Config
  • Utils

    • Connection Status
    • general
    • showpad-interactive
    • showpad-upload
  • Components

    • Accordion
    • BackButton
    • Breadcrumb
    • ByltButton
    • Hamburger
    • Icon
    • Logo
    • Loader
    • Modal
    • Popup
    • Prompt
    • ProgressBar
    • TextLoader
  • Composables

    • useDebugMode
    • useConnectionStatus
  • Utils

    • dom
    • props
  • General

    • General
    • Tracking
  • Components

    • Accordion
    • ActionButton
    • AssetItem
    • AssetList
    • BackButton
    • ConfigGenButton
    • Logo
    • Media
    • Modal
    • Popup
    • Prompt
    • SPButton
    • SPRouterView
    • SPTrackedRouterLink
    • TextLoader
    • View
  • Composables

    • useConnectionStatus
  • Stores

    • useAppsDbStore
    • useBreadcrumbStore
    • useShowpadAPIStore
    • useShowpadSDKStore
    • useSpConfigStore
    • useSpStore
    • useSpTrackingStore
  • The New Kit

    • General
    • Installation & Usage
    • ACF Blocks
    • PHPCS
    • Functions
    • Vite
    • WP Config
    • Staging Deployment
  • Best Practices

    • Page Structure
    • Fonts/Typography
  • Todo
GitHub
  • Popup

Popup

import Popup, { determineOffCanvasType } from '@bbc/front-end-kit/js/components/Popup';

Introduction

The Popup component manages a javascript dialog dom element so we can easily create popups, provide them with content and manage their animations easily. It extends from Component so it comes with all the benefits of that class and its parents.

Why dialog?

The power of the dialog element lies in the fact that it can be added anywhere and at any level of the DOM tree. Dialog will always be rendered in a shadow dom element that can be found at the bottom of the DOM tree. No issues with indexes or having content related popups be spread accross the DOM tree to bypass tha index and context issues of the elements.

Why the Popup class?

THe popup clas adds extra structure around the dialog component so that it can be easily extended and adapted to custom situations while also still focussing on consistent code structure and maintainability. Thanks to this class it is easy to add extra animations using other libraries like gsap

Getting started

Javascript

The class can both be extended or initialised directly. As always it is advised to extend into a child class of the specific type of popup that is meant to be managed. Example: A popup containing a login, could be extended to a class called LoginPopup

class LoginPopup extends Popup {
    constructor(args = {}) {
        super(args);
    }

    // some extra methods / getters & setters specific to this type of popup
    get isChecking() {
        return this._isChecking
    }
}

When initialising:

const loginPopup = new LoginPopup({
    $el: $loginPopupElement
});

DOM Element

The DOM element should resemble the following structure.

<dialog class="popup">
    <div class="popup__container">
        <!-- popup content here -->

        <button class="popup__close-btn">Close</button>
    </div>
</dialog>

Attribute initialisation

The Popup component is also able to look for it's triggers by itself during construction. Set a data-popup attribute with a value (id/key) on the element of the popup and the popup will automatically look for triggers in the dom that use a data-popup-trigger attribute with the same value (id/key). Every trigger that matches the query will be registered as a trigger of the instance an thus will toggle toe popup when it is clicked.

<!-- triggers -->
<a href="#" data-popup-trigger="my-popup">Anchor trigger</a>
<button data-popup-trigger="my-popup">Button trigger</button>
<div data-popup-trigger="my-popup">Div trigger</div>


<!-- the popup they will trigger -->
<dialog class="popup" data-popup="my-popup">
    <div class="popup__container">
        <!-- popup content here -->

        <button class="popup__close-btn">Close</button>
    </div>
</dialog>

Animations

The Popup component allows the build-in animations to be overridden during initialization. The custom show/hide methods can be passed using the animation object as a parameter of the c

Override the animations

Simply during initialisation:

const popup = new Popup({
    animations: {
        show: myCustomShowAnimation,
        hide: myCustomHideAnimation
    }
})

Although it is advised to extend from Popup first and override the args object of the constructor before it is passed to the Popup constructor

class CustomPopup extends Popup {
    constructor (args = {}) {

        // override args parameters
        args.animations = args.animations || {};
        args.animations.show = myCustomShowAnimation;
        args.animations.hide = myCustomHideAnimation;

        // run super constructor
        super(args);
    }
}

Animation method requirements

Custom animation methods require to return a Promise that resolves when the animation is completes. This lets the Popup know when the animation is complete so that the logic that is waiting can continue.

The method will be called using the instance as scope (this) and receives the options as parameter comming from the show/hide/toggle methods

function myCustomShowAnimation (options = {}) {
    return new Promise(resolve => {
        // the custom animation using gsap in this case
        gsap.to(this.$el, {
            opacity: 1,
            onComplete: resolve
        })
        ///
    })
}

Off-canvas behavior

The default built-in animation for the popup is a simple fade in. But it also incorporates more Off-Canvas like animations that can simply be triggered by adding the right css class to the DOM element it manages. Using css it will also make sure it sticks to the desired side of the screen like off-canvas elements are required to do. Possible classes to trigger this behavior.

  • --oc-top: Triggers the animation to slide in from the top of the screen
  • --oc-right: Triggers the animation to slide in from the right of the screen
  • --oc-bottom: Triggers the animation to slide in from the bottom of the screen
  • --oc-left: Triggers the animation to slide in from the left of the screen
    <!-- popup used as mobile navigation that needs to slide in from the right -->
    <dialog class="popup --oc-right --mobile-nav">
        ...
    </dialog>

API

constructor(args = {})

The constructor method initialises the new Popup instance.

Parameters

  • args: The configuration object used by the constructor to initialise the Popup in the desired way.
    • $triggers: List of DOM elements that will be used to toggle the state of the Popup (DOM element or list of DOM elements)
    • isVisible (Boolean, default false): Sets the initial visibility state of the popup. Applied instantly without animation.
    • quitOnEscape: Flag to allow the Popup to hide when the user presses ESC button
    • animations: Object that allows the built-in show/hide animations to be overridden with different methods
      • show: Method that will be used to show the popup
      • hide: Method that will be used to hide the popup
    • ... Component properties

Methods

show (options)

Show the popup using either a built-in animation or a custom animation defined during initilisation

Parameters
  • options: Object with extra customisations during runtime that will be applied while the show state is triggered
    • instant: skips the animation if true (default: false)

Tips

If true is passed instead of an options object, it will be interpreted as a value for the instant property of the options object. The animation will be skipped

Return

Returns a Promise that resolves when the transition is done.

hide (options)

Hide the popup using either a built-in animation or a custom animation defined during initilisation

Parameters
  • options: Object with extra customisations during runtime that will be applied while the hide state is triggered
    • instant: skips the animation if true (default: false)

Tips

If true is passed instead of an options object, it will be interpreted as a value for the instant property of the options object. The animation will be skipped

Return

Returns a Promise that resolves when the transition is done.

toggle (options)

Toggles the popup depending on it's current state using either a built-in animation or a custom animation defined during initilisation. It will use the corresponding show/hide method behind the scenes.

Parameters
  • options: Object with extra customisations during runtime that will be applied while the hide state is triggered
    • instant: skips the animation if true (default: false)
    • show (Boolean, optional): Force show (true) or hide (false) instead of toggling.

Tips

If true is passed instead of an options object, it will be interpreted as a value for the instant property of the options object. The animation will be skipped

Return

Returns undefined. Use show() or hide() directly if you need to await the animation Promise.

addTrigger (...triggers)

Registers extra DOM element as triggers to toggle the Poppup on click.

Parameters
  • ...triggers: The DOM element to register. Every parameter passed will be registered as trigger. Parmeters may also be arrays of triggers.
Return

Return undefined

// single element
popup.addTrigger($trigger)

// multiple elments over parameters
popup.addTrigger($trigger1, $trigger2, $trigger3)

// array of triggers
popup.addTrigger([$trigger1, $trigger2, $trigger3])

// combination of both
popup.addTrigger($trigger1, [$trigger2, $trigger3], $trigger4)

removeTrigger (...$triggers)

Unregisters one or more DOM elements as triggers and removes their click listeners.

Warning

The bound listener reference is removed via removeEventListener, but the source notes this is still work-in-progress and may not fully decouple all listener edge cases. A console warning is logged for each removed trigger.

Parameters
  • ...$triggers: The DOM element(s) to unregister. Accepts the same spread/array forms as addTrigger.

Exported methods

determineOffCanvasType()

Inspects this._$el's classlist and returns the off-canvas direction ('top', 'right', 'bottom', 'left') or null if none of the --oc-* classes are present. Called internally by the hide animation to determine slide direction.

Getters & Setters

isVisible

Returns the current visibility state of the Popup.

  • true: visible
  • false: not visible

isTransitioning

Returns the state of the animation it is currently performing

  • true: transitioning/animating
  • false: idle (not animating)

$triggers

Returns the list of triggers that are registered to toggle the popup on click.

Events

Popup dispatches events using the EventDispatcher's api since Component extends from EventDispatcher

before-show

The moment before the show animation starts. isTransitioning and isVisible remain false

after-show

The moment right after the show animation ends. isTransitioning back to false, isVisible is now true

before-hide

The moment before the hide animation starts. isTransitioning is still false, isVisible is still true

after-hide

The moment right after the hide animation ends. isTransitioning and isvisible are back to false

trigger-click

Fires when the user clicks one of the registered triggers, before the toggle is processed. Access via e.detail:

  • e.detail.$trigger: The trigger element that was clicked.
  • e.detail.originalEvent: The original click event.

close-click

Fires when the user clicks the .popup__close-btn element, before hide() is called. Access via e.detail:

  • e.detail.$closeButton: The close button element that was clicked.
  • e.detail.originalEvent: The original click event.

escape

Fires when the user presses Escape (and quitOnEscape is true), before hide() is called. Access via e.detail:

  • e.detail.originalEvent: The original keyup event.

Private properties

_$triggers

Array of registered triggers the instance is listening to so it can be toggled when they are clicked.

_$closeBtn

The close button DOM element of the popup instance

_quitOnEscape

Flag used to determine if the popup should listen to keyup events on the escape key to close itself.

_isVisible

Flag to track the visibility state of the popup instance

_isTransitioning

Flag to track if the popup instance is transitioning to a new state.

_animations

Object containing the animations the instance uses for the show/hide transitions It contains 2 properties:

  • show: The show animation function
  • hide: The hide animation function These methods can be set using the constructor.

External dependencies

  • GSAP: Greensock's animation library for the built-in animations
  • lodash: For some quick and usefull utility methods like:
  • flattenDeep: Flattens a multilevel array to a single level one.

Todo

  • Add the possibility to define the off-canvas type through the constructor
  • Create a toggleable class that will provide the toggle logic for both Popup and Tab
  • Add a method to the instance to request the instance to do a new search for triggers in the DOM and maybe clear out triggers that were removed.
Edit this page
Last Updated: 4/27/26, 12:56 PM
Contributors: Nicolas Jaenen