(base): Añade componente Dialog

Sustituye `PropsOp::Translate` por `Rename` para que los temas traduzcan
atributos `data-dialog-*` al vocabulario propio (p. ej. `data-bs-*` en
Bootsier).
This commit is contained in:
Manuel Cillero 2026-08-26 21:56:10 +02:00
parent 3c67d9d04c
commit 76c5cb9b76
11 changed files with 362 additions and 42 deletions

View file

@ -283,6 +283,68 @@ input:disabled + label {
color: var(--val-color--text--muted);
}
/*
* Dialog component
*/
.dialog {
padding: 0;
width: 100%;
max-width: 32rem;
color: var(--val-color--text);
background-color: var(--val-color--bg);
border: none;
border-radius: 0.5rem;
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
}
.dialog::backdrop {
background-color: rgba(0, 0, 0, 0.5);
}
.dialog-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
padding: 1rem 1.25rem;
border-bottom: 1px solid color-mix(in srgb, var(--val-color--border) 15%, var(--val-color--bg));
}
.dialog-title {
margin: 0;
font-size: 1.125rem;
font-weight: 600;
}
.dialog-close {
width: 1.5rem;
height: 1.5rem;
padding: 0;
line-height: 1;
color: var(--val-color--text--muted);
background-color: transparent;
border: none;
cursor: pointer;
}
.dialog-close::before {
content: "\2715";
}
.dialog-close:hover {
color: var(--val-color--text);
}
.dialog-body {
padding: 1.25rem;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
gap: 0.5rem;
padding: 1rem 1.25rem;
border-top: 1px solid color-mix(in srgb, var(--val-color--border) 15%, var(--val-color--bg));
}
/*
* Dropdown component
*/

View file

@ -0,0 +1,45 @@
// Abre y cierra los componentes `Dialog` de Basic (elemento `<dialog>` nativo) interpretando el
// vocabulario de atributos `data-dialog-*`, común a todos los temas: Bootsier traduce estos mismos
// nombres a los suyos propios (`data-bs-*`) en `setup()` para que el JS de Bootstrap los reconozca,
// así el marcado de un disparador o de un botón de cierre es idéntico en los dos temas. Sin
// dependencias: ni htmx, ni Bootstrap, ni ninguna otra librería.
// Abre el diálogo referenciado por `data-dialog-target` al pulsar un elemento con
// `data-dialog-toggle="modal"`.
document.addEventListener("click", function (event) {
var toggle = event.target.closest('[data-dialog-toggle="modal"]');
if (!toggle) {
return;
}
var target = toggle.getAttribute("data-dialog-target");
var dialog = target && document.querySelector(target);
if (!(dialog instanceof HTMLDialogElement)) {
return;
}
event.preventDefault();
dialog.showModal();
});
// Cierra el `<dialog>` ascendente más cercano al pulsar un elemento con
// `data-dialog-dismiss="modal"`.
document.addEventListener("click", function (event) {
var dismiss = event.target.closest('[data-dialog-dismiss="modal"]');
if (!dismiss) {
return;
}
var dialog = dismiss.closest("dialog");
if (dialog) {
event.preventDefault();
dialog.close();
}
});
// Cierra el diálogo al pulsar sobre el fondo (`::backdrop`): un clic ahí llega con el propio
// `<dialog>` como `event.target`, porque el fondo no forma parte de su caja de contenido.
document.querySelectorAll("dialog.dialog").forEach(function (dialog) {
dialog.addEventListener("click", function (event) {
if (event.target === dialog) {
dialog.close();
}
});
});