K
kmodals

Documentation

Everything you need to build delightful, accessible modals. Avoid maintenance headaches and focus on building your product.

Getting Started

kmodals is a lightweight, event-driven browser modal library with promise-based helpers, responsive dialog, sheet and drawer presentations, and accessible focus management. The distributed browser builds are self-contained and include their styles.

Local npm package

Download and extract your licensed ZIP, then install its folder:

npm install ./path/to/kmodals
import kmodal from 'kmodals';

Script Tag (UMD)

Self-host the licensed file; CSS is bundled:

<script src="/assets/kmodals.umd.js"></script>

ES Modules (ESM)

Import the licensed file directly. CSS is included:

import kmodal from './vendor/kmodals.es.js';

Basic Usage

// Using constructor with content and options
const myModal = new kmodal('Hello World!', {
  type: 'info',
  header: 'Welcome'
});

// Using constructor with a single options object
new kmodal({
  header: 'Alert',
  content: 'Something happened!',
  type: 'alert'
});

// Using static confirm (Promise<boolean>)
const accepted = await kmodal.confirm('Are you sure?');
if (accepted) {
  // do something
}

Options API

Pass as the second argument to the kmodal constructor or the static helpers.

Option Type Default Description
type 'info' | 'alert' | 'confirm' | 'error' | 'loading' | 'prompt' | 'clean' 'info' Visual style and behavior
header string '' Header HTML/text
content string '' Body HTML/text (if not 1st arg)
icon boolean true Show type-specific icon
theme 'auto' | 'light' | 'dark' | 'glass' | 'editorial' | 'contrast' | string 'auto' Theme; can append variants like 'light danger'
presentation 'dialog' | 'sheet' | 'drawer' 'dialog' Surface layout
placement 'center' | 'bottom' | 'top' | 'start' | 'end' 'center' Surface position; centered sheets and drawers resolve to sensible edges
motion 'fade' | 'scale' | 'slide' | 'spring' | 'none' 'scale' Opening and closing transform style
density 'comfortable' | 'compact' 'comfortable' Spacing and control density
responsive { breakpoint?, presentation?, placement?, density? } | false false Overrides layout at or below a viewport breakpoint
fadeShowTime number 200 Show animation duration (ms)
fadeHideTime number 200 Hide animation duration (ms)
buttonOneText string 'Accept' Primary button text
buttonTwoText string 'Cancel' Secondary button text
showCloseButton boolean false Show the 'x' close button
buttonsOrder 'web' | 'windows' 'web' Visual order
hideOnButtonOneClick boolean true Hide on primary button click
hideOnButtonTwoClick boolean Type-dependent Defaults to true for confirm and prompt, otherwise false
destructive boolean false Adds destructive styling and initially focuses the safer action
hideOnBgClick boolean true Hide on background click
hideOnEscape boolean true Hide on Escape key
hideOnBack boolean true Hide on browser back
hideOnClick boolean false Hide on dialog click
persistent boolean false Prevents closing via background, dialog click, Escape key or browser back
removeAfterHide boolean true Remove instance after hide
autoShow boolean true Show automatically on creation
trapFocus boolean true Trap focus for a11y
restoreFocus boolean true Restore previous focus
initialFocus string | null null CSS selector to focus
unique boolean false Prevent multiple at once
hideScrollbars boolean false Hide body scrollbars
promptInputDefault string '' Default prompt value
promptPlaceholder string '' Prompt placeholder
sanitizeContent boolean false XSS sanitize html
sanitizeAllowedTags string[] ['b', 'i', 'em', 'strong', 'p', 'div', 'span', 'a', 'ul', 'ol', 'li', 'br', 'hr', 'blockquote'] Allowed HTML tags for sanitization

Properties

  • element: HTMLElement | null — Root DOM element of the modal (read-only)

Instance Methods

  • show(): Promise<void> — Displays the modal
  • hide(): Promise<void> — Hides the modal
  • setContent(content: string): void — Updates body content
  • setHeader(content: string): void — Updates header content
  • setIcon(type: 'info' | 'alert' | 'confirm' | 'error' | 'loading' | 'prompt' | 'clean'): void — Changes the modal icon
  • setOption<K extends keyof KModalOptions>(key: K, value: KModalOptions[K]): void — Updates an option and refreshes UI

Static Methods

Convenient shortcuts that return a Promise (except for loading).

  • kmodal.info(content, options?): Promise<void>
  • kmodal.alert(content, options?): Promise<void>
  • kmodal.error(content, options?): Promise<void>
  • kmodal.confirm(content, options?): Promise<boolean>
  • kmodal.prompt(content, options?): Promise<string | null>
  • kmodal.loading(content, options?): kmodal — returns the instance
  • kmodal.setDefaults(options: Partial<KModalOptions>): void — Sets global defaults
  • kmodal.resetDefaults(): void — Resets global defaults

Events

kmodals uses standard CustomEvent. All events receive CustomEvent object as an argument. The modal instance is available in event.detail.instance.

Event Description Cancelable
beforeShow Before show animation Yes
show After show animation No
beforeHide Before hide animation Yes
hide After hide animation No
buttonOneClick Primary button clicked Yes
buttonTwoClick Secondary button clicked Yes
modalClick Click inside dialog Yes
backgroundClick Click on overlay Yes
escape Escape key pressed Yes
back Back navigation Yes
remove When destroyed Yes
const modal = new kmodal('Check console');

// Using event listener
modal.addEventListener('show', (event) => {
  console.log('Modal instance:', event.detail.instance);
  console.log('Modal is fully visible!');
});

// Preventing closure
modal.addEventListener('buttonOneClick', (event) => {
  if (someCondition) {
    event.preventDefault(); // stops the modal from hiding
  }
});

Callback Wrappers

You can pass these callbacks directly in the options object. Callback wrappers receive instance and CustomEvent object as arguments.

Option Event Equivalent Description
onBeforeShow beforeShow Called before the modal is shown
onShow show Called after show animation finishes
onBeforeHide beforeHide Called before the modal starts hiding
onHide hide Called after hide animation finishes
onButtonOneClick buttonOneClick Called when primary button is clicked
onButtonTwoClick buttonTwoClick Called when secondary button is clicked
onModalClick modalClick Called when clicking inside the modal
onBackgroundClick backgroundClick Called when clicking the overlay
onEscape escape Called when Escape key is pressed
onBack back Called on browser back navigation
onRemove remove Called when instance is destroyed
new kmodal('Hello!', {
  onShow: (instance, event) => {
    console.log('Modal is visible!', event.detail.instance, event);
  },
  onButtonOneClick: (instance, event) => {
    console.log('Button clicked!');
    // event.preventDefault(); // You can also prevent default here
  }
});

Advanced Examples

Form with Validation

const formContent = `
  <form id="my-form">
    <label>Name:</label>
    <input type="text" id="name" required class="w-full mt-1 border rounded px-2 py-1">
    <p id="error-msg" class="text-red-600 hidden">Name is required!</p>
  </form>`;

const modal = new kmodal(formContent, {
  header: 'User Info',
  buttonOneText: 'Save',
  onButtonOneClick: (instance, event) => {
    const nameInput = document.getElementById('name');
    if (!nameInput.value) {
      event.preventDefault(); // Stop modal from closing
      document.getElementById('error-msg').classList.remove('hidden');
    } else {
      console.log('Form submitted:', nameInput.value);
    }
  }
});

Custom Multi‑Step Modal

let step = 1;
const modal = new kmodal('Step 1: Welcome!', {
  buttonOneText: 'Next',
  onButtonOneClick: (instance, event) => {
    if (step === 1) {
      event.preventDefault(); // Stay open
      instance.setContent('Step 2: Almost done.');
      instance.setOption('buttonOneText', 'Finish');
      step = 2;
    }
  }
});

Persistent Loading

const loader = kmodal.loading('Processing data...');

// Simulate async task
setTimeout(() => {
  loader.hide();
  kmodal.info('Data processed successfully!');
}, 3000);

Layouts, Placement and Motion

Use dialog for a conventional centered surface, sheet for an edge panel that is usually anchored to the bottom, and drawer for a tall side panel. Placement and motion are independent and validated at runtime.

Responsive bottom sheet

new kmodal('Review the details.', {
  header: 'Order summary',
  presentation: 'dialog',
  motion: 'slide',
  responsive: {
    breakpoint: 768,
    presentation: 'sheet',
    placement: 'bottom',
    density: 'compact'
  }
});

Side drawer

new kmodal('Account settings', {
  header: 'Settings',
  presentation: 'drawer',
  placement: 'end',
  motion: 'slide',
  showCloseButton: true
});

fade changes opacity, scale grows a centered surface, slide enters from the effective edge, spring adds a shorter overshooting movement, and none disables the transition. Reduced-motion preferences suppress animated transforms automatically.

Themes

Built‑in themes: light, dark, glass, editorial, and contrast. By default, auto follows the system preference.

new kmodal('Glass Style', { theme: 'glass' });

Button Variants

Append a variant to change the primary button color:

  • primary, info, success, warning, danger, darky
new kmodal('Delete account?', { theme: 'light danger' });

CSS Customization

You can easily customize kmodals using CSS variables. Define them in your :root or a specific scope.

Variable Default Value Description
--kmodal-overlay rgb(15 23 42 / 56%) Background overlay color
--kmodal-surface #ffffff Dialog background color
--kmodal-text #344054 Base text color
--kmodal-heading #101828 Header text color
--kmodal-radius 20px Border radius for dialog and buttons
--kmodal-shadow 0 8px 24px rgba(0, 0, 0, 0.3) Dialog box shadow
--kmodal-accent #3157d5 Primary button background
--kmodal-secondary #ffffff Secondary button background
--kmodal-accent-contrast #ffffff Primary button text color
--kmodal-secondary-text #344054 Secondary button text color
--kmodal-width 32rem Default dialog width
--kmodal-font-family Inter, system-ui, sans-serif Main font family
--kmodal-z-index 10 Base z-index for the modal overlay

Compatibility aliases such as --kmodal-btn-primary and --kmodal-border-radius remain available, but new themes should prefer the semantic tokens above.

.kmodal-brand {
  --kmodal-accent: #10b981;
  --kmodal-radius: 8px;
  --kmodal-width: 36rem;
}

Accessibility and Security

kmodals provides dialog semantics, accessible labelling, focus trapping and restoration, top-modal keyboard handling, stacked-modal coordination, background isolation, reduced-motion behavior, and forced-colors support. Applications remain responsible for meaningful headings, explicit action labels, appropriate initial focus, and accessible custom HTML.

HTML trust model: header, content, setHeader(), and setContent() accept HTML. Enable sanitizeContent: true whenever values may contain untrusted input.
new kmodal(untrustedHtml, {
  header: 'Preview',
  sanitizeContent: true,
  sanitizeAllowedTags: ['p', 'strong', 'em', 'a', 'br']
});

Framework Integration

kmodals is framework-independent and mounts under document.body. Create instances only from client-side lifecycle code. For one-shot interactions, use the static promise helpers. If a component may unmount while a modal remains open, keep the returned instance and call hide() during cleanup. Do not construct a modal during server rendering, where document is unavailable.

Localization

By default, kmodals uses English labels (Accept, Cancel). You can easily override these per instance using the buttonOneText and buttonTwoText options.

new kmodal('Are you sure?', {
  buttonOneText: 'Yes, proceed',
  buttonTwoText: 'No, cancel'
});

Global Configuration

You can set global defaults for all modal instances in two ways:

1. Using JavaScript

kmodal.setDefaults({
  theme: 'light',
  buttonOneText: 'OK',
  buttonTwoText: 'Cancel'
});

2. Using Data Attributes

When using the UMD version, you can provide defaults directly on the script tag:

<script 
  src="./kmodals.umd.js" 
  data-theme="glass" 
  data-button-one-text="Accept">
</script>

Note: For boolean values use "true"/"false". For type option use data-default-type.

Changelog

Version 4.0.0

  • Dialog, sheet, and drawer presentations with responsive overrides
  • Light, dark, glass, editorial, contrast, and automatic themes
  • Configurable placement, motion, density, and destructive confirmations
  • Accessible focus management and DOMPurify-backed HTML sanitization
  • ES module, UMD, and TypeScript declaration builds