Skip to content

feat(vue): allow useAutoAnimate with Vue component ref#186

Merged
justin-schroeder merged 1 commit intoformkit:release/0.8.5from
marshallswain:patch-1
Aug 27, 2025
Merged

feat(vue): allow useAutoAnimate with Vue component ref#186
justin-schroeder merged 1 commit intoformkit:release/0.8.5from
marshallswain:patch-1

Conversation

@marshallswain
Copy link
Copy Markdown
Contributor

This adds support for using useAutoAnimate with a component as the parent.

When you add ref="parent" to a component, the element is found at parent.value.$el. This update checks for component elements or a plain HTML element ref.

Without this change, you have to create a proxy ref to extract the element in the onMounted hook, like this:

<script setup lang="ts">
const [autoAnimateParent, enable] = useAutoAnimate()

// create a "proxy" dragParent ref which will hold a ref to the component.
const dragParent = ref()

// assign the component's $el to the autoAnimateParent once the DOM mounts
onMounted(() => (autoAnimateParent.value = dragParent.value?.$el))
</script>

<template>
  <VueDraggable
    ref="dragParent"
    v-model="items"
    :animation="300"
  >
    <!-- ... -->
  </VueDraggable>
</template>

This PR doesn't address the types. I'm not sure the best way to handle that. I did pull the code into a local repo to try it out and took this screenshot of the type issue.

Screenshot 2023-12-19 at 7 39 52 PM

If you want to instruct me how to proceed on the types, I'll update the code. Or feel free to edit this PR directly.

This adds support for using `useAutoAnimate` with a component as the parent.  

When you add `ref="parent"` to a component, the element is found at `parent.value.$el`.  This update checks for component elements or a plain HTML element ref.
@vercel
Copy link
Copy Markdown

vercel Bot commented Dec 20, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
auto-animate ✅ Ready (Inspect) Visit Preview 💬 Add feedback Dec 20, 2023 3:47am

@marshallswain
Copy link
Copy Markdown
Contributor Author

I just noticed this other PR. #159

I think their objective is the same, based on this comment: #159 (comment).

@marshallswain
Copy link
Copy Markdown
Contributor Author

Sorry about being lazy with the types. I'm not a TS ninja by any means, but I took a crack at it. Maybe you'll see a more optimal way to handle the ElementOrComponentRef type:

import { onMounted, ref, watchEffect } from 'vue'
import type { Directive, Plugin, Ref } from 'vue'
import type {
  AnimationController,
  AutoAnimateOptions,
  AutoAnimationPlugin,
} from '@formkit/auto-animate'
import autoAnimate, { vAutoAnimate as autoAnimateDirective,
} from '@formkit/auto-animate'

export const vAutoAnimate: Directive<
  HTMLElement,
  Partial<AutoAnimateOptions>
> = autoAnimateDirective

export const autoAnimatePlugin: Plugin = {
  install(app) {
    app.directive('auto-animate', vAutoAnimate)
  },
}

export type ElementOrComponentRef<T extends Element> = T & { $el?: Element }

/**
 * AutoAnimate hook for adding dead-simple transitions and animations to Vue.
 * @param options - Auto animate options or a plugin
 * @returns A template ref. Use the `ref` attribute of your parent element
 * to store the element in this template ref.
 */
export function useAutoAnimate<T extends Element>(
  options?: Partial<AutoAnimateOptions> | AutoAnimationPlugin,
): [Ref<ElementOrComponentRef<T>>, (enabled: boolean) => void] {
  const element = ref<ElementOrComponentRef<T>>()
  let controller: AnimationController | undefined
  function setEnabled(enabled: boolean) {
    if (controller)
      enabled ? controller.enable() : controller.disable()
  }
  onMounted(() => {
    watchEffect(() => {
      const el = element.value?.$el || element.value
      if (el instanceof HTMLElement)
        controller = autoAnimate(el, options || {})
    })
  })

  return [element as Ref<T>, setEnabled]
}

@justin-schroeder justin-schroeder changed the base branch from master to release/0.8.5 August 27, 2025 15:35
@justin-schroeder justin-schroeder merged commit 3a4c6bf into formkit:release/0.8.5 Aug 27, 2025
@justin-schroeder
Copy link
Copy Markdown
Member

I might rework this a bit, but I think the concept is solid. thanks! Sorry its taken a couple years haha 🤣

justin-schroeder added a commit that referenced this pull request Sep 5, 2025
* test(e2e): add Playwright visual tests (video + pixel diffs); stabilize animation waits; upload videos in CI

* fix: jumping when aligned at bottom (#69) (#211)

* fix: jumping when aligned at bottom (#69)

* chore: use const instead of let

* test(e2e): add Playwright visual tests (video + pixel diffs); stabilize animation waits; upload videos in CI

---------

Co-authored-by: Justin Schroeder <justin@formkit.com>

* fix: #69 — nice

* Adding bun to installation instructions (#205)

* feat: allow useAutoAnimate with Vue component ref (#186)

This adds support for using `useAutoAnimate` with a component as the parent.  

When you add `ref="parent"` to a component, the element is found at `parent.value.$el`.  This update checks for component elements or a plain HTML element ref.

* feat: adds component support to useAutoAnimate for Vue

* Investigate and resolve auto-animate issues (#225)

* Improve offscreen handling, Vue integration, and cleanup in AutoAnimate

Co-authored-by: justin <justin@formkit.com>

* Add e2e tests for various autoAnimate scenarios and behaviors

Co-authored-by: justin <justin@formkit.com>

* chore: remove playwright report

* Angular 17.1+ support (#206)

* Angular >v17.1 support

* angular example rewrite

* Angular docs change

* Update package.json

* angular pnpm-lock & usage import fix

* ' -> " typo fix

---------

Co-authored-by: Gergely Dremak <gergely.dremak@hu.bosch.com>
Co-authored-by: Justin Schroeder <justin@formkit.com>

* chore: lockfile bump

* fix: bottom anchored animations

* chore: remove local claude

* fix: restore bottom-aligned animation fix from PR #211 and fix CI test failures

- Restored deltaBottom/deltaRight checks to detect anchored elements
- Fixed immediate position updates after animations (debounce=false)
- Restored proper parent coordinate calculations in deletePosition
- Added named export for autoAnimate to fix exports test
- Fixed flaky framework animation tests by ensuring elements are visible
- Added scrollIntoViewIfNeeded and increased wait times for CI reliability

All bottom-jump-fix tests now pass across all browsers

* fix: add build step to CI and make tests more robust for slow environments

- Added 'pnpm build' step to GitHub Actions workflow before running tests
- Fixed exports test by ensuring dist files are built in CI
- Made framework animation tests more robust with polling approach
- Added browser-specific timeouts for WebKit compatibility
- Increased wait times and retry attempts for slow CI environments

* fix: no nuxt build on ci

* chore: gh caching

---------

Co-authored-by: Maik Kowol <maik.s.kowol@gmail.com>
Co-authored-by: Abi <86650485+iabii@users.noreply.github.com>
Co-authored-by: Marshall Thompson <marshall@creativeideal.net>
Co-authored-by: Gergely Dremák <gergely089@gmail.com>
Co-authored-by: Gergely Dremak <gergely.dremak@hu.bosch.com>
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

Successfully merging this pull request may close these issues.

2 participants