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 modalhide(): Promise<void>— Hides the modalsetContent(content: string): void— Updates body contentsetHeader(content: string): void— Updates header contentsetIcon(type: 'info' | 'alert' | 'confirm' | 'error' | 'loading' | 'prompt' | 'clean'): void— Changes the modal iconsetOption<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 instancekmodal.setDefaults(options: Partial<KModalOptions>): void— Sets global defaultskmodal.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.
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