Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/TheSerchCp/SEAM/llms.txt

Use this file to discover all available pages before exploring further.

SEAM’s feedback layer covers three distinct interaction patterns: modals pause the user flow and request a decision, toasts surface non-blocking status messages that dismiss themselves, and the loader overlay signals that a long-running operation is in progress. All three are appended directly to document.body at call time, so they work from any page or component without a pre-existing mount point.
Modal is an async function that builds a confirmation dialog, appends it to document.body, and resolves once the markup is in the DOM. Interaction is handled entirely via event listeners — no polling, no returned promises for the user’s decision.
import { Modal } from '../../shared/components/Modal.js';

Props

title
string
default:"\"Confirmar\""
Text displayed in the modal header.
body
string
default:"\"\""
HTML string rendered in the modal body. You can include any markup here.
onConfirm
async function | null
default:"null"
Called when the user clicks the confirm button. If it returns an object with success: false the modal stays open; any other return value (including undefined) closes the modal. The confirm button is disabled for the duration of the async call.
onCancel
function | null
default:"null"
Called when the user clicks Cancel or clicks the backdrop. The modal is removed before onCancel is invoked.
confirmText
string
default:"\"Confirmar\""
Label for the confirm button.
cancelText
string
default:"\"Cancelar\""
Label for the cancel button.
confirmBtnId
string | null
default:"null"
Optional custom id for the confirm button. Useful when external code needs to reference the button (e.g. FormModal uses this to wire up FormValidator).
isDanger
boolean
default:"false"
When true, the confirm button is rendered in red (bg-red-600) instead of blue.
Modal appends its element directly to document.body. Clicking the semi-transparent backdrop or the Cancel button removes the element from the DOM. If onConfirm returns { success: false }, the modal remains visible so the user can correct the problem.

Real-world example — Delete user confirmation (users.page.js)

import { Modal } from '../../shared/components/Modal.js';

window.deleteUser = async function (idUser) {
    await Modal({
        title: '¿Eliminar usuario?',
        body: '<p class="text-sm text-gray-300">Esta acción <strong>no se puede deshacer</strong>. ¿Estás seguro?</p>',
        onConfirm: async () => {
            try {
                await removeUser(idUser);
                EventBus.emit('page:reload');
                return { success: true };
            } catch (error) {
                return { success: false, error: error.message };
            }
        },
        confirmText: 'Eliminar',
        isDanger: true,
    });
};

FormModal

FormModal composes Modal and Form into a single create/edit dialog. It auto-generates the form body from a fields array, initialises any SelectField dropdowns, and wires up a FormValidator instance — all inside a single await call.
import { FormModal } from '../../shared/components/FormModal.js';

Props

title
string
required
Modal header text, e.g. 'Agregar Usuario' or 'Editar Usuario'.
formId
string
default:"\"dynamic-form\""
The id written onto the inner <form> element. Should be unique per open modal.
fields
array
required
Same fields array accepted by Form. See Form Components for the full field descriptor shape.
schema
object
default:"{}"
Validation schema passed to FormValidator. When non-empty, FormValidator is instantiated and attach() is called automatically after the modal renders. The confirm button is disabled until the form passes all rules.
confirmText
string
default:"\"Guardar\""
Label for the confirm button.
cancelText
string
default:"\"Cancelar\""
Label for the cancel button.
onConfirm
async function
required
Receives a formData plain object (built from new FormData(form)) and must return { success: true } to close the modal or { success: false } to keep it open.

Add User flow from users.page.js

import { FormModal } from '../../shared/components/FormModal.js';

addBtn.addEventListener('click', async () => {
    await FormModal({
        title: 'Agregar Usuario',
        formId: 'user-form',
        fields: [
            { name: 'name',            label: 'Nombre',               type: 'text',     placeholder: 'Juan Pérez',       required: true },
            { name: 'email',           label: 'Email',                type: 'email',    placeholder: 'juan@example.com', required: true },
            { name: 'password',        label: 'Contraseña',           type: 'password', placeholder: '••••••••',         required: true },
            { name: 'confirmPassword', label: 'Confirmar Contraseña', type: 'password', placeholder: '••••••••',         required: true },
            { name: 'idRole',          label: 'Rol',                  type: 'select',   options: roleOptions,            required: true },
        ],
        schema: USER_SCHEMA,
        onConfirm: async (formData) => {
            try {
                await createUser({
                    full_name: formData.name,
                    email:     formData.email,
                    password:  formData.password,
                    roleId:    parseInt(formData.idRole),
                });
                EventBus.emit('page:reload');
                return { success: true };
            } catch (error) {
                return { success: false, error: error.message };
            }
        },
    });
});
FormModal calls Modal() internally, which appends the dialog directly to document.body. You do not need to set innerHTML on a container element — simply await FormModal(...) and the modal appears immediately. It removes itself from the DOM when the user confirms or cancels.

Toast

Toast creates a small notification banner, appends it to a #toast-container div (creating the container if it does not exist), and removes it after duration milliseconds.
import { Toast, showSuccess, showError, showWarning, showInfo } from '../../shared/components/Toast.js';

Toast({ message, type, duration })

message
string
required
The notification text displayed inside the banner.
type
"success" | "error" | "warning" | "info"
default:"\"info\""
Controls the colour scheme and icon:
TypeBorder/BG tintIcon
successEmeraldfa-circle-check
errorRedfa-circle-xmark
warningAmberfa-triangle-exclamation
infoBluefa-circle-info
duration
number
default:"3000"
Auto-dismiss delay in milliseconds. Pass 0 to keep the toast on screen until the user manually closes it.
Toast returns the generated toastId string so you can remove it programmatically if needed:
const id = Toast({ message: 'Processing…', type: 'info', duration: 0 });
// later…
document.getElementById(id)?.remove();

Convenience functions

Four pre-configured wrappers cover the most common cases:
showSuccess('Usuario creado correctamente.');      // duration: 3 000 ms
showError('Error al conectar con el servidor.');   // duration: 4 000 ms
showWarning('Esta acción no se puede deshacer.');  // duration: 3 500 ms
showInfo('Sincronizando datos…');                  // duration: 3 000 ms

EventBus toast events

Toast.js registers five EventBus listeners at module load time. Any part of the application — including ApiClient — can trigger a toast without importing Toast directly:
EventPayloadDefault duration
toast:show{ message, type?, duration? }Matches type default
toast:success{ message, duration? }3 000 ms
toast:error{ message, duration? }4 000 ms
toast:warning{ message, duration? }3 500 ms
toast:info{ message, duration? }3 000 ms
import { EventBus } from '../../core/EventBus.js';

// Trigger a success toast from anywhere in the application:
EventBus.emit('toast:success', { message: 'Cambios guardados.' });

// Or use the generic event with an explicit type:
EventBus.emit('toast:show', { message: 'Operación completada.', type: 'success', duration: 5000 });
ApiClient emits toast:success on successful responses and toast:error on failed ones automatically, so most API interactions surface feedback to the user with no additional code.

Loader

Loader is a singleton full-screen overlay with a spinning indicator and a customisable message. It is ideal for wrapping slow operations such as page transitions or large data fetches.
import { Loader } from '../../shared/components/Loader.js';

Methods

Loader.show(message)
method
Creates the #global-loader element if it does not yet exist, sets the message text, and makes the overlay visible. Default message: 'Cargando...'.
Loader.show('Guardando cambios…');
Loader.update(message)
method
Updates the message text while the loader is already visible — useful for multi-step operations.
Loader.update('Procesando imagen…');
Loader.hide()
method
Hides the overlay.
Loader.hide();

EventBus integration

Loader also responds to operation:progress events so services can drive the overlay without importing Loader directly:
EventBus.emit('operation:progress', { status: 'start',      message: 'Cargando usuarios…' }); // shows loader
EventBus.emit('operation:progress', { status: 'processing', message: 'Validando datos…'   }); // updates message
EventBus.emit('operation:progress', { status: 'success' });                                    // hides loader
EventBus.emit('operation:progress', { status: 'error' });                                      // hides loader
Always call Loader.hide() (or emit operation:progress with status: 'success' or 'error') in both the success and catch branches of an async operation. Forgetting to hide the loader will leave the full-screen overlay blocking all user interaction.

Typical usage pattern

import { Loader }      from '../../shared/components/Loader.js';
import { showSuccess, showError } from '../../shared/components/Toast.js';

async function loadPage() {
    Loader.show('Cargando datos…');
    try {
        const data = await fetchSomeData();
        renderTable(data);
        showSuccess('Datos cargados.');
    } catch (err) {
        showError('No se pudo cargar la información.');
    } finally {
        Loader.hide();
    }
}

Build docs developers (and LLMs) love