ngneat / dialog

👻 A simple to use, highly customizable, and powerful modal for Angular Applications
https://ngneat.github.io/dialog/
MIT License
394 stars 38 forks source link

Open dialog at non-zero drag offset #110

Open jemand771 opened 1 year ago

jemand771 commented 1 year ago

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Performance issue
[x] Feature request
[ ] Documentation issue or request
[ ] Support request
[ ] Other... Please describe:

Current behavior

Right now, dialogs open in the center of the screen but can be moved after creation using dialogRef.resetDrag({x: -500, y: 0}). However, calling this from the dialog's ngOnInit method will result in an unpleasant jump: The dialog opens in the center and gets transformed to the side a second or so later.

Expected behavior

I'd like a way to launch dialogs in non-center positions from the start. In its most rudimentary form, this could be an initial dragOffset as part of a dialog's config. In fact, there already is an input for this, but it's not exposed via the dialog config. (I tried doing that, but it didn't work. no idea why.)

Ideally, I'd want a setting with some common predefined positions. e.g. left, right, top, ... to automatically snap the dialog to a side of the screen. That way, I don't have to do any ugly screen and dialog size calculations to pass pixel offsets to resetDrag.

I've already tried to hack this in externally via css, like so:

/* open in top center */
div.ngneat-dialog-backdrop {
    align-items: start;
}

/* open in center left */
div.ngneat-dialog-backdrop {
    justify-content: left;
}

but that moves the whole draggable area, not just the dialog within it. -> dialog is draggable beyond the screen edge on one side but doesn't go all the way to the edge on the other side

Minimal reproduction of the problem with instructions

n/a

What is the motivation / use case for changing the behavior?

While it's common to open dialogs in the center (full user attention, sense of urgency), sometimes they're better fit in a different place. (e.g. close to the control element that triggered the dialog) To avoid having to hardcode positions, a simple "to the left" or "to the top" option would be ideal.

Environment


Angular version: 16.1.6


Browser: n/a
- [x] Chrome (desktop) version 115
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [x] Firefox version 102 (esr)
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

For Tooling issues: n/a
- Node version: XX  
- Platform:  

Others:

jemand771 commented 1 year ago

I found the culprit for the weird behavior I've been experiencing.

at first, I tried this here

          <div
            *ngIf="config.draggable"
            class="ngneat-drag-marker"
            dialogDraggable
+           [dialogDragOffset]="{x: 400, y: 0}"]
            [dialogDragEnabled]="true"
            [dialogDragTarget]="dialog"
            [dragConstraint]="config.dragConstraint"
          ></div>

but since the DraggableDirective only applies the input via this.translate() once, that had no effect.

as a sanity check, I added this here

        <div
          #dialog
          class="ngneat-dialog-content"
          [class.ngneat-dialog-resizable]="config.resizable"
          [ngStyle]="styles"
+         style="transform: translateX(400px)"
          role="dialog"
        >

and sure enough, I get something:

chrome_goR4Sc9P3B

here's the reason:

  @keyframes dialog-open {
    0% {
      transform: translateX(50px);
    }
    100% {
      transform: none;
    }
  }

  animation: dialog-open 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);

this overrides transform values passed in any other way for the first 0.4 seconds.

I'm still not sure how to solve this and hope somebody else can pick this up unless I manage to figure something out later.