Skip to content
This repository has been archived by the owner on Nov 8, 2023. It is now read-only.
/ vue-transition-a11y Public archive

A extended version of the Vue <transition> component, which takes 'prefers-reduced-motion' in to account.

License

Notifications You must be signed in to change notification settings

mrtnvh/vue-transition-a11y

Repository files navigation

vue-transition-a11y

https://vanhoofmaarten.github.io/vue-transition-a11y/

Vue transition component with a11y considerations.

Problem

When using the Vue transitions component with CSS transitions or CSS Animations, it's pretty easy to disable these for users who prefer this.

<transition name="slide-fade">
  <!-- ... -->
</transition>

Transitions

.slide-fade-enter-active,
.slide-fade-leave-active {
  transition: all 0.3s ease;
}

@media (prefers-reduced-motion: reduce) {
  .slide-fade-enter-active,
  .slide-fade-leave-active {
    transition: none;
  }
}

Animations

.slide-fade-enter-active,
.slide-fade-leave-active {
  animation: bounce-in 0.5s;
}

@media (prefers-reduced-motion: reduce) {
  .slide-fade-enter-active,
  .slide-fade-leave-active {
    animation: none;
  }
}

@keyframes bounce-in {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1.5);
  }
  100% {
    transform: scale(1);
  }
}

Globally

@media (prefers-reduced-motion: reduce) {
  * {
    animation: none !important;
    transition: none !important;
  }
}

But when using JavaScript Hooks, things get a little more complicated.

<transition
  v-on:before-enter="beforeEnter"
  v-on:enter="enter"
  v-on:after-enter="afterEnter"
  v-on:enter-cancelled="enterCancelled"
  v-on:before-leave="beforeLeave"
  v-on:leave="leave"
  v-on:after-leave="afterLeave"
  v-on:leave-cancelled="leaveCancelled"
>
  <!-- ... -->
</transition>
// ...
methods: {
  beforeEnter(el) {
    // ...
  },
  enter(el, done) {
    // ...
    done()
  },
  afterEnter(el) {
    // ...
  },
  enterCancelled(el) {
    // ...
  },
  beforeLeave(el) {
    // ...
  },
  leave(el, done) {
    // ...
    done()
  },
  afterLeave(el) {
    // ...
  },
  leaveCancelled(el) {
    // ...
  }
}

Where in all of these functions are you going to disable your complex animations?

Using the window.matchMedia functionality, you could check if the user's preferences.

const prefersReducedMotion = window.matchMedia(
  'screen and (prefers-reduced-motion: reduce)',
).matches;

// Stop every animation method if prefersReducedMotion === false

A bit over the top, don't you think?

Solution

To tackle this problem and enable Vue developers to make complex, re-usable and accessible transitions and animations with the transition component, I've created this component.

What is does is very simple. If the user prefers reduced motion, don't render the transition component. If not, render it.

This way, JavaScript Hooks aren't called when unnecessary

Easy.

API

The vue-transition-a11y components API extends the standard Vue transition API.

Props

Prop Default value Description
reduceMotion true Take the prefers-reduced-motion: reduce media query in to account.

Usage

<div class="outer">
  <transition-a11y>
    <div class="inner">
      <!-- ... -->
    </div>
  </transition-a11y>
</div>

License

MIT

Copyright (c) 2020 Maarten Van Hoof

About

A extended version of the Vue <transition> component, which takes 'prefers-reduced-motion' in to account.

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published