Make generic popups be modal dialogs

- Switch generic popups to actual <dialog> elements
- Move toastr settings from html to JS
- Add style variable for animation duration (to re-use in CSS)
- Remember focus of popup on stacking pop-up close to switch back to the element you started out in
- Fix keybinds of popups to only act on actual result-triggering controls
- Fix toastr appearing behind popups by dynamically moving the container inside the currently open dialog
- Improve autofocus on popup open
- Make cleaner and prettier popup animations, and tie them to the animation speed
-
This commit is contained in:
Wolfsblvt
2024-05-30 05:11:23 +02:00
parent 311fb261a4
commit 6c3118549f
5 changed files with 315 additions and 186 deletions

View File

@ -227,7 +227,7 @@ import { appendFileContent, hasPendingFileAttachment, populateFileAttachment, de
import { initPresetManager } from './scripts/preset-manager.js';
import { evaluateMacros } from './scripts/macros.js';
import { currentUser, setUserControls } from './scripts/user.js';
import { POPUP_TYPE, callGenericPopup } from './scripts/popup.js';
import { POPUP_TYPE, callGenericPopup, fixToastrForDialogs } from './scripts/popup.js';
import { renderTemplate, renderTemplateAsync } from './scripts/templates.js';
import { ScraperManager } from './scripts/scrapers.js';
import { SlashCommandParser } from './scripts/slash-commands/SlashCommandParser.js';
@ -263,6 +263,19 @@ showLoader();
// Yoink preloader entirely; it only exists to cover up unstyled content while loading JS
document.getElementById('preloader').remove();
// Configure toast library:
toastr.options.escapeHtml = true; // Prevent raw HTML inserts
toastr.options.timeOut = 4000; // How long the toast will display without user interaction
toastr.options.extendedTimeOut = 10000; // How long the toast will display after a user hovers over it
toastr.options.progressBar = true; // Visually indicate how long before a toast expires.
toastr.options.closeButton = true; // enable a close button
toastr.options.positionClass = "toast-top-center"; // Where to position the toast container
toastr.options.onHidden = () => {
// If we have any dialog still open, the last "hidden" toastr will remove the toastr-container. We need to keep it alive inside the dialog though
// so the toasts still show up inside there.
fixToastrForDialogs();
}
// Allow target="_blank" in links
DOMPurify.addHook('afterSanitizeAttributes', function (node) {
if ('target' in node) {
@ -910,6 +923,8 @@ export function displayOnlineStatus() {
*/
export function setAnimationDuration(ms = null) {
animation_duration = ms ?? ANIMATION_DURATION_DEFAULT;
// Set CSS variable to document
document.documentElement.style.setProperty('--animation-duration', `${animation_duration}ms`);
}
export function setActiveCharacter(entityOrKey) {
@ -5431,7 +5446,7 @@ export function setSendButtonState(value) {
async function renameCharacter() {
const oldAvatar = characters[this_chid].avatar;
const newValue = await callPopup('<h3>New name:</h3>', 'input', characters[this_chid].name);
const newValue = await callGenericPopup('<h3>New name:</h3>', POPUP_TYPE.INPUT, characters[this_chid].name);
if (newValue && newValue !== characters[this_chid].name) {
const body = JSON.stringify({ avatar_url: oldAvatar, new_name: newValue });