diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 68b610bc..7d9c8c9d 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -20,6 +20,7 @@ $form-feedback-valid-color: $black; $form-feedback-invalid-color: $magenta; $form-feedback-icon-valid-color: $black; $component-active-bg: $magenta; +$zindex-modal-backdrop: 0; $spacers: ( 2-plus: 0.75rem diff --git a/app/javascript/controllers/modal_controller.js b/app/javascript/controllers/modal_controller.js new file mode 100644 index 00000000..3a614b80 --- /dev/null +++ b/app/javascript/controllers/modal_controller.js @@ -0,0 +1,40 @@ +import { Controller } from "stimulus"; + +export default class extends Controller { + static targets = ["modal", "backdrop"]; + + show(event = undefined) { + event?.preventDefault(); + + this.modalTarget.style.display = "block"; + this.backdropTarget.style.display = "block"; + this.modalTarget.setAttribute("role", "dialog"); + this.modalTarget.setAttribute("aria-modal", true); + this.modalTarget.removeAttribute("aria-hidden"); + + window.document.body.classList.add("modal-open"); + + setTimeout(() => { + this.modalTarget.classList.add("show"); + this.backdropTarget.classList.add("show"); + }, 1); + } + + hide(event = undefined) { + event?.preventDefault(); + + this.backdropTarget.classList.remove("show"); + this.modalTarget.classList.remove("show"); + + this.modalTarget.setAttribute("aria-hidden", true); + this.modalTarget.removeAttribute("role"); + this.modalTarget.removeAttribute("aria-modal"); + + setTimeout(() => { + this.modalTarget.style.display = ""; + this.backdropTarget.style.display = ""; + }, 500); + + window.document.body.classList.remove("modal-open"); + } +} diff --git a/app/views/bootstrap/_modal.haml b/app/views/bootstrap/_modal.haml new file mode 100644 index 00000000..b57fc94e --- /dev/null +++ b/app/views/bootstrap/_modal.haml @@ -0,0 +1,38 @@ +-# + # Modal + + @see {https://getbootstrap.com/docs/4.6/components/modal/} + @see {https://github.com/bullet-train-co/nice_partials/issues/99} + @param :id [String] El ID del modal + @param :modal_content_attributes [Hash] Atributos para el contenido del modal + @param :hide_actions [Array] Acciones al ocultar el modal + @yield :ID_body Contenido + @yield :ID_header Contenido del header (opcional) + @yield :ID_footer Contenido del pie (opcional) + @example + = render 'bootstrap/modal', id: 'algo' do |partial| + - content_for :algo_header do + = 'título' + - content_for :algo_body do + = 'contenido' + - content_for :algo_footer do + = 'pie' + +- local_assigns[:hide_actions] ||= [] +- local_assigns[:hide_actions] << 'click->modal#hide' +- local_assigns[:modal_content_attributes] ||= {} + +.modal.fade{ tabindex: -1, aria: { hidden: 'true' }, data: { target: 'modal.modal' } } + .modal-backdrop.fade{ data: { target: 'modal.backdrop', action: local_assigns[:hide_actions].join(' ') } } + .modal-dialog.modal-dialog-scrollable.modal-dialog-centered + .modal-content{ **local_assigns[:modal_content_attributes] } + - if (header = yield(:"#{id}_header")).present? + .modal-header= header + + .modal-body= yield(:"#{id}_body") + + .modal-footer.flex-nowrap + - if (footer = yield(:"#{id}_footer")) + = footer + - else + %button.btn.btn-secondary.m-0{ type: 'button', data: { action: 'modal#hide' } }= t('.close')