Skip to content
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

Handle Closed <dialog> and <popover> Animations #536

Open
mobalti opened this issue Dec 29, 2024 · 1 comment
Open

Handle Closed <dialog> and <popover> Animations #536

mobalti opened this issue Dec 29, 2024 · 1 comment

Comments

@mobalti
Copy link
Contributor

mobalti commented Dec 29, 2024

Keyframe animations are a great way to add smooth transitions between the closed and shown states of <dialog> and <popover>. This approach has several advantages:

  • No need to provide a @starting-style.
  • No need to explicitly enable discrete animations.
  • Unlike transition, animation is supported by all major browsers for shown states; only the closed state animations are currently limited to Chromium-based browsers.

For the shown state, no additional work is needed as animations work out of the box. However, for the closed state, adding the display property to the out animation is required, as shown in this example:

.animate-slide-up-down {
    /* motionOK */
    @media (prefers-reduced-motion: no-preference) {
        animation: slide-out-down 0.5s var(--ease-3);

        &:popover-open {
            /* Built-in animation from Open Props */
            animation: var(--animation-slide-in-up);
        }
    }
}

@keyframes slide-out-down {
    from {
        display: block;
    }
    to {
        transform: translateY(100%);
    }
}

The same applies to fade animations:

.animate-fade-in-out {
    opacity: 0;

    /* motionOK */
    @media (prefers-reduced-motion: no-preference) {
        animation: fade-out 0.5s var(--ease-3) forwards;

        &:popover-open {
            /* Built-in animation from Open Props */
            animation: var(--animation-fade-in) forwards;
        }
    }
}

@keyframes fade-out {
    from {
        display: block;
        opacity: 1;
    }
    to {
        opacity: 0;
    }
}

See this example on CodePen and click one of the cards to view the animations live:
https://codepen.io/mobalti/pen/EaYVJgr


Summary

To handle animations when dialogs and popovers are closed, we can either:

  1. Update the current "out" animation props by adding the display property to the keyframes (if there are no side effects).
  2. Create new "out" animation props specifically for handling the closed state.
@argyleink
Copy link
Owner

  1. Switch to transitions because using keyframes can be a bummer

we also want to avoid changing the display property of a popover or dialog.

here's some examples of dialogs, to show

  • what's possible given the snippets i'm about to share
  • why you want to avoid changing the display property

transitions for popover and dialog in one snippet

here's the styles needed to transition both popover and dialog (transform property not included). not sure we'll want to provide this exactly, or use the individual snippets. worth talking about. also, nesting isnt used because there were nesting limitations when I authored it. but now, these limits are fixed, and it could be turned into 1 snippet.

/* enable transitions */
[popover], dialog, ::backdrop {
  transition: 
    display 1s allow-discrete, 
    overlay 1s allow-discrete, 
    opacity 1s;
  opacity: 0;
}

/* ON STAGE */
:popover-open,
:popover-open::backdrop,
[open],
[open]::backdrop {
  opacity: 1;
}

/* OFF STAGE */
@starting-style {
  :popover-open,
  :popover-open::backdrop,
  [open],
  [open]::backdrop {
    opacity: 0;
  }
}

Working example https://codepen.io/argyleink/pen/zYbQBOm

basics of transitioning just a dialog:

dialog {
  transform: translateY(20px);
  
  &, &::backdrop {
    transition: 
      display 1s allow-discrete,
      overlay 1s allow-discrete,
      opacity 1s,
      transform 1s;

    opacity: 0;
  }
  
  &[open] {
    opacity: 1;
    transform: translateY(0px);
    
    &::backdrop {
      opacity: 0.8;
    }
  }
  
  @starting-style {
    &[open], 
    &[open]::backdrop {
      opacity: 0;
    }
    
    &[open] {
      transform: translateY(20px);
    }
  }
}

basics of transitioning just a popover:

[popover] {
  &, &::backdrop {
    transition: 
      display .5s allow-discrete, 
      overlay .5s allow-discrete, 
      opacity .5s;
    opacity: 0;
  }

  &:popover-open {
    opacity: 1;

    &::backdrop {
      opacity: 0.5;
    }
  }

  @starting-style {
    &:popover-open,
    &:popover-open::backdrop {
      opacity: 0;
    }
  }
}

all in all, i totally agree these styles should be included in normalize (or as imports) and we should switch away from the previous dialog work into a more flexible solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants