-
Notifications
You must be signed in to change notification settings - Fork 47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Click and dragging outside the modal closes it #712
Comments
@calebporzio just tested this with the default modal from the docs and can confirm the issue. Mousing down anywhere inside the modal (inputs, whitespace, anywhere) and then dragging the mouse outside of the modal and then releasing causes the modal to close. Volt component <?php
use Livewire\Volt\Component;
new class extends Component {
//
};
?>
<div>
<flux:modal.trigger name="edit-profile">
<flux:button>Edit profile</flux:button>
</flux:modal.trigger>
<flux:modal name="edit-profile" class="md:w-96 space-y-6">
<div>
<flux:heading size="lg">Update profile</flux:heading>
<flux:subheading>Make changes to your personal details.</flux:subheading>
</div>
<flux:input label="Name" placeholder="Your name" />
<flux:input label="Date of birth" type="date" />
<div class="flex">
<flux:spacer />
<flux:button type="submit" variant="primary">Save changes</flux:button>
</div>
</flux:modal>
</div> |
In this discussion there have already been a couple of inputs, I considered this to be a breaking change and would have loved an actual a flag to restore the previous behavior but there have been no updates to that discussion since. |
@danielrona Have you tried adding |
Yeah I can confirm that using |
Ok I've worked out what the issue is and submitted a PR with a fix! PR description below The scenarioCurrently if a user mouses down inside a modal, drags their mouse outside, and then releases their mouse button, the modal closes. <?php
use Livewire\Volt\Component;
new class extends Component {
//
};
?>
<div>
<flux:modal.trigger name="edit-profile">
<flux:button>Edit profile</flux:button>
</flux:modal.trigger>
<flux:modal name="edit-profile" class="md:w-96 space-y-6">
<div>
<flux:heading size="lg">Update profile</flux:heading>
<flux:subheading>Make changes to your personal details.</flux:subheading>
</div>
<flux:input label="Name" placeholder="Your name" />
<flux:input label="Date of birth" type="date" />
<div class="flex">
<flux:spacer />
<flux:button type="submit" variant="primary">Save changes</flux:button>
</div>
</flux:modal>
</div> The problemDialog elements don't have a native click outside. So we have a click listener on the dialog element that checks to see if the click originated outside of the dialog, to determine whether it should be closed or not. if (this.options().clickOutside) {
// Clicking outside the dialog should close it...
this.el.addEventListener('click', e => {
// Clicking the ::backdrop pseudo-element is treated the same as clicking the <dialog> element itself
// Therefore, we can dissregard clicks on any element other than the <dialog> element itself...
if (e.target !== this.el) return
// Again, because we can't listen for clicks on ::backdrop, we have to test for intersection
// between the click and the visible parts of the dialog elements...
if (clickHappenedOutside(this.el, e)) {
this.cancel()
e.preventDefault(); e.stopPropagation()
}
})
} The problem is that this check happens at the time the click listener is fired, which is when the mouse up event happens. It is detecting that the mouse is outside of the dialog at that point in time and closing the modal. The solutionTo fix this, we need to keep track of whether the mouse down event was fired outside of the dialog as well as detecting if the click happened outside of the dialog. This way we can ensure that the click both started and ended outside of the dialog, and if so, then close it. let startedOutside = false
// If a user mouses down inside the dialog, and then drags the mouse outside the dialog before releasing the mouse button,
// the dialog should not close so we need to track whether the mouse down was initially triggered outside the dialog...
this.el.addEventListener('mousedown', e => {
// Clicking the ::backdrop pseudo-element is treated the same as clicking the <dialog> element itself
// Therefore, we can dissregard clicks on any element other than the <dialog> element itself...
if (e.target !== this.el) return
startedOutside = clickHappenedOutside(this.el, e)
})
// Clicking outside the dialog should close it...
this.el.addEventListener('click', e => {
// Clicking the ::backdrop pseudo-element is treated the same as clicking the <dialog> element itself
// Therefore, we can dissregard clicks on any element other than the <dialog> element itself...
if (e.target !== this.el) return
// Again, because we can't listen for clicks on ::backdrop, we have to test for intersection
// between the click and the visible parts of the dialog elements...
if (startedOutside && clickHappenedOutside(this.el, e)) {
this.cancel()
e.preventDefault(); e.stopPropagation()
}
// Reset started outside ready for the next click...
startedOutside = false
}) Fixes #712 |
Quick summary
When dragging outside a modal (probably any dialog) it gets closed. The click event triggers on mouse up, and has the clientX & clientY from where the mouse was released.
Workaround/fix
I was able to fix this by adding this code inside
dialogable.js
:The text was updated successfully, but these errors were encountered: