Arrow keys: ← previous · → next 17 of 35
@nodedk/modal
0.5.1 stable

modal#

Browser dialogs that load server-rendered HTML, with layouts for modals and nested prompts.

Install#

Install in a NodeDK application and copy the layouts and assets:

npm i @nodedk/modal
mkdir -p app/assets/js app/assets/css app/assets/img app/layouts
cp node_modules/@nodedk/modal/build/assets/js/*.js app/assets/js/
cp node_modules/@nodedk/modal/build/assets/css/*.css app/assets/css/
cp node_modules/@nodedk/modal/build/assets/img/* app/assets/img/
cp node_modules/@nodedk/modal/build/layouts/*.js app/layouts/

Add these entries to the application’s existing bundle configuration:

// app/config/bundle.js
module.exports = {
  css: ['/css/modal.css', '/css/prompt.css'],
  js: ['/js/modal.js']
}

Load bundles with state.style(['/bundle.css']) and state.script(['/bundle.js']) in the main layout. Add empty containers near the end of its body:

<div class="modal" style="display: none"></div>
<div class="prompt" style="display: none"></div>

Usage#

Register routes that return modal and prompt content:

// app/config/routes.js
var { html } = require('@nodedk/page')
var Modal = require('../layouts/modal.js')
var Prompt = require('../layouts/prompt.js')

module.exports = [
  {
    name: 'modal',
    methods: 'GET',
    paths: '/modal',
    handler: async function (state) {
      return Modal(state, { title: 'Account' }, [
        html`<p>Account settings.</p>
          <button
            onclick="window.openModal(this)"
            data-modal=".prompt"
            data-href="/prompt"
          >
            Confirm changes
          </button>`
      ])
    }
  },
  {
    name: 'prompt',
    methods: 'GET',
    paths: '/prompt',
    handler: async function (state) {
      return Prompt(state, { title: 'Confirm' }, [
        html`<p>Save your changes?</p>`
      ])
    }
  }
]

Open a dialog from a link or button:

<a
  href="/modal"
  data-modal=".modal"
  onclick="
    openModal(this)
    return false
  "
>
  Account settings
</a>

<button
  onclick="openModal(this)"
  data-modal=".modal"
  data-href="/modal"
  data-title="Edit account"
>
  Edit account
</button>

openModal(trigger, callback)#

Returns a Promise with no value. trigger is an element or a selector for one. callback() is optional and runs after content loads; its return value is not awaited.

Trigger attributes:

  • data-modal: target selector; defaults to .modal.
  • data-href or href: URL whose HTML replaces the dialog contents. Without a URL, opens the existing contents.
  • data-title: HTML that replaces .modal-title after loading.

The helper marks the dialog with .modal-current, adds .modal-open to the body, and runs inline scripts in the loaded content. Use trusted HTML.

closeModal(target, options = {})#

Hides and empties the dialog. target is its selector or a trigger element with data-modal; the element form defaults to .modal. The helper returns no value.

options.scroll: false keeps the body’s modal state and scroll position, which is useful when closing a prompt over an open modal.

closeModal('.prompt', { scroll: false })
closeModal('.modal')

Layouts#

Modal(state, props = {}, slot = []) and Prompt(state, props = {}, slot = []) return HTML strings.

  • state: application state, accepted for the NodeDK layout convention.
  • props.title: title text, default ''; escaped by the layout.
  • props.type: additional frame classes, default ''.
  • slot: array of rendered HTML strings, joined with newlines.

Development#

npm run build

Copies assets and layouts into build. Packaging runs this build automatically.

Created by Vidar Eldøy