Skip to content

Animations

Classes for animating elements. In addition to Alpine's x-transition, those can be used by custom components when extending Harmonia.

Class names

ClassDescription
scale-95scale: 95% 95%
scale-105scale: 105% 105%
ClassDescription
duration-100transition-duration: 100ms;
duration-200transition-duration: 200ms;
duration-300transition-duration: 300ms;
ClassDescription
ease-outtransition-timing-function: var(--ease-out, cubic-bezier(0, 0, 0.2, 1));
ease-lineartransition-timing-function: linear;
ClassDescription
-translate-x-fulltranslate: -100% var(--tw-translate-y);
translate-x-fulltranslate: 100% var(--tw-translate-y);
-translate-y-fulltranslate: var(--tw-translate-x) -100%;
translate-y-fulltranslate: var(--tw-translate-x) 100%;
-translate-x-4translate: calc(var(--spacing) * -4) var(--tw-translate-y);
translate-x-4translate: calc(var(--spacing) * 4) var(--tw-translate-y);
-translate-y-4translate: var(--tw-translate-x) calc(var(--spacing) * -4);
translate-y-4translate: var(--tw-translate-x) calc(var(--spacing) * 4);
ClassDescription
transition-alltransition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, pointer-events;
transition-timing-function: var(--default-transition-timing-function, cubic-bezier(0.4, 0, 0.2, 1));
transition-duration: var(--default-transition-duration, 150ms);
transition-colorstransition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;
transition-timing-function: var(--default-transition-timing-function, cubic-bezier(0.4, 0, 0.2, 1));
transition-duration: var(--default-transition-duration, 150ms);
transition-shadowtransition-property: box-shadow;
transition-timing-function: var(--default-transition-timing-function, cubic-bezier(0.4, 0, 0.2, 1));
transition-duration: var(--default-transition-duration, 150ms);
transition-opacitytransition-property: opacity;
transition-timing-function: var(--default-transition-timing-function, cubic-bezier(0.4, 0, 0.2, 1));
transition-duration: var(--default-transition-duration, 150ms);
transition-transformtransition-property: transform, translate, scale, rotate;
transition-timing-function: var(--default-transition-timing-function, cubic-bezier(0.4, 0, 0.2, 1));
transition-duration: var(--default-transition-duration, 150ms);
transition-[opacity,scale]transition-property: opacity, scale;
transition-timing-function: var(--default-transition-timing-function, cubic-bezier(0.4, 0, 0.2, 1));
transition-duration: var(--default-transition-duration, 150ms);
motion-reduce:transition-noneDisables all transitions when the "Reduce Motion" accessibility setting is enabled

Examples

Scale and Opacity

WARNING

Users with vestibular motion disorders often enable the "Reduce Motion" accessibility setting on their devices.

Be sure to account for this preference in your implementation, as excessive motion can cause discomfort or disorientation for affected users.

html
<div class="vbox gap-4" x-data="ScaleController">
  <button x-h-button @click="toggle()" x-text="isShown ? 'Hide' : 'Show'"></button>
  <div x-h-alert class="hidden scale-95 opacity-0 transition-[opacity,scale] duration-200 ease-out motion-reduce:transition-none" x-ref="alert">
    <svg x-h-icon.circle-info role="img" aria-label="information"></svg>
    <div x-h-alert-title>Alert</div>
  </div>
</div>
<script>
  Alpine.data('ScaleController', () => ({
    isShown: false,
    toggle() {
      this.isShown = !this.isShown;
      // Use differnet logic when the user has disabled animations/enabled reduced motion
      if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
        if (this.isShown) {
          this.$refs.alert.classList.remove('hidden', 'scale-95', 'opacity-0');
        } else {
          this.$refs.alert.classList.add('hidden', 'scale-95', 'opacity-0');
        }
      } else if (this.isShown) {
        this.$refs.alert.classList.remove('hidden');
        Alpine.nextTick(() => {
          // Reading 'offsetHeight' forces the browser to apply pending styles first.
          // This guarantees that the animation will always happen.
          this.$refs.alert.offsetHeight;
          this.$refs.alert.classList.remove('scale-95', 'opacity-0');
        });
      } else {
        this.$refs.alert.addEventListener(
          'transitionend',
          () => {
            this.$refs.alert.classList.add('hidden');
          },
          { once: true }
        );
        this.$refs.alert.classList.add('scale-95', 'opacity-0');
      }
    },
  }));
</script>

Translate

html
<div class="border">
  <svg x-h-icon class="size-12 -translate-x-4" data-link="/harmonia/logo/harmonia.svg" role="img" aria-label="Harmonia logo"></svg>
</div>
<div class="border">
  <svg x-h-icon class="size-12 translate-x-4" data-link="/harmonia/logo/harmonia.svg" role="img" aria-label="Harmonia logo"></svg>
</div>
<div class="border">
  <svg x-h-icon class="size-12 -translate-y-4" data-link="/harmonia/logo/harmonia.svg" role="img" aria-label="Harmonia logo"></svg>
</div>
<div class="border">
  <svg x-h-icon class="size-12 translate-y-4" data-link="/harmonia/logo/harmonia.svg" role="img" aria-label="Harmonia logo"></svg>
</div>