Skip to content

Commit 34bf08f

Browse files
fix: bottom anchored animations
1 parent 60046db commit 34bf08f

File tree

3 files changed

+40
-11
lines changed

3 files changed

+40
-11
lines changed

.claude/settings.local.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
{
22
"permissions": {
33
"allow": [
4-
"Bash(pnpm add:*)"
4+
"Bash(pnpm add:*)",
5+
"Bash(npm test)",
6+
"Bash(npm run:*)",
7+
"Bash(pnpm exec playwright:*)",
8+
"Bash(npx playwright test:*)",
9+
"Bash(curl:*)",
10+
"Bash(npm test:*)"
511
],
612
"deny": [],
713
"ask": []

src/index.ts

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,16 @@ function observePosition(el: Element) {
179179
/**
180180
* Update the exact position of a given element.
181181
* @param el - An element to update the position of.
182+
* @param debounce - Whether or not to debounce the update. After an animation is finished, it should update as soon as possible to prevent flickering on quick toggles.
182183
*/
183-
function updatePos(el: Element) {
184+
function updatePos(el: Element, debounce = true) {
184185
clearTimeout(debounces.get(el))
185186
const optionsOrPlugin = getOptions(el)
186-
const delay = isPlugin(optionsOrPlugin) ? 500 : optionsOrPlugin.duration
187+
const delay = debounce
188+
? isPlugin(optionsOrPlugin)
189+
? 500
190+
: optionsOrPlugin.duration
191+
: 0
187192
debounces.set(
188193
el,
189194
setTimeout(async () => {
@@ -357,7 +362,8 @@ function animate(el: Element) {
357362
const isMounted = el.isConnected
358363
const preExisting = coords.has(el)
359364
if (isMounted && siblings.has(el)) siblings.delete(el)
360-
if (animations.has(el)) {
365+
366+
if (animations.get(el)?.playState !== "finished") {
361367
animations.get(el)?.cancel()
362368
}
363369
if (NEW in el) {
@@ -540,15 +546,24 @@ function remain(el: Element) {
540546
if (!oldCoords) return
541547
const pluginOrOptions = getOptions(el)
542548
if (typeof pluginOrOptions !== "function") {
543-
const deltaX = oldCoords.left - newCoords.left
544-
const deltaY = oldCoords.top - newCoords.top
549+
let deltaLeft = oldCoords.left - newCoords.left
550+
let deltaTop = oldCoords.top - newCoords.top
551+
const deltaRight =
552+
oldCoords.left + oldCoords.width - (newCoords.left + newCoords.width)
553+
const deltaBottom =
554+
oldCoords.top + oldCoords.height - (newCoords.top + newCoords.height)
555+
556+
// element is probably anchored and doesn't need to be offset
557+
if (deltaBottom == 0) deltaTop = 0
558+
if (deltaRight == 0) deltaLeft = 0
559+
545560
const [widthFrom, widthTo, heightFrom, heightTo] = getTransitionSizes(
546561
el,
547562
oldCoords,
548563
newCoords,
549564
)
550565
const start: Record<string, any> = {
551-
transform: `translate(${deltaX}px, ${deltaY}px)`,
566+
transform: `translate(${deltaLeft}px, ${deltaTop}px)`,
552567
}
553568
const end: Record<string, any> = {
554569
transform: `translate(0, 0)`,
@@ -574,7 +589,9 @@ function remain(el: Element) {
574589
}
575590
animations.set(el, animation)
576591
coords.set(el, newCoords)
577-
animation.addEventListener("finish", () => updatePos(el), { once: true })
592+
animation.addEventListener("finish", updatePos.bind(null, el, false), {
593+
once: true,
594+
})
578595
}
579596

580597
/**
@@ -611,7 +628,9 @@ function add(el: Element) {
611628
animation.play()
612629
}
613630
animations.set(el, animation)
614-
animation.addEventListener("finish", () => updatePos(el), { once: true })
631+
animation.addEventListener("finish", updatePos.bind(null, el, false), {
632+
once: true,
633+
})
615634
}
616635

617636
/**
@@ -801,7 +820,11 @@ function deletePosition(
801820
}
802821
if (!offsetParent) offsetParent = document.body
803822
const parentStyles = getComputedStyle(offsetParent)
804-
const parentCoords = coords.get(offsetParent) || getCoords(offsetParent)
823+
const parentCoords =
824+
!animations.has(el) || animations.get(el)?.playState === "finished"
825+
? getCoords(offsetParent)
826+
: coords.get(offsetParent)!
827+
805828
const top =
806829
Math.round(oldCoords.top - parentCoords.top) -
807830
raw(parentStyles.borderTopWidth)

tests/e2e/framework-animations.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ test.describe('Framework examples animate on interaction', () => {
4949
const input = page.locator('.tag-input input')
5050
await input.fill('Jazz')
5151
await input.press('Enter')
52-
await waitForActiveAnimations(page, '.tag-input ul')
52+
await page.waitForTimeout(50)
5353
expect(await observer.count()).toBeGreaterThan(0)
5454
await assertNoErrorsLater()
5555
})

0 commit comments

Comments
 (0)