feat(cart): open the cart drawer only after the drip has run down
Docker Image bauen und veroeffentlichen / build-and-push (push) Successful in 2m20s
Docker Image bauen und veroeffentlichen / build-and-push (push) Successful in 2m20s
The drawer used to slide in 180 ms after the honey drop landed and covered the glow and the drip on the cart icon. It now waits until the drip has finished (about 1.4 s). Without a visible flight (reduced motion, icon off-screen) it still opens almost at once. The drip timing lives in cart-flight.tsx so both files share one source. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
15a457f66e
commit
1daef79026
2 files changed
+21
-11
No files matched your search
@@ -7,6 +7,16 @@ const FLIGHT_EVENT = "wh:cart-flight";
|
||||
const LAND_EVENT = "wh:cart-landed";
|
||||
const FLIGHT_MS = 700;
|
||||
|
||||
// Nachspiel am Warenkorb-Symbol (components/cart-landing-effect.tsx): der
|
||||
// Tropfen, der nach der Landung am Korb herunterlaeuft. Hier definiert,
|
||||
// weil die Schublade erst oeffnen soll, wenn er fertig abgeperlt ist.
|
||||
export const DRIP_DELAY_S = 0.3;
|
||||
export const DRIP_DURATION_S = 1.1;
|
||||
const DRAWER_AFTER_DRIP_MS = Math.round((DRIP_DELAY_S + DRIP_DURATION_S) * 1000);
|
||||
// Ohne sichtbaren Flug (reduzierte Bewegung, Symbol nicht im Bild) gibt es
|
||||
// nichts abzuwarten — die Schublade oeffnet fast sofort.
|
||||
const DRAWER_WITHOUT_FLIGHT_MS = 180;
|
||||
|
||||
/**
|
||||
* Startet den Flug eines Honigtropfens vom geklickten Knopf zum
|
||||
* Warenkorb-Symbol. Aufrufer legen den Artikel mit openDrawer: false in den
|
||||
@@ -28,9 +38,10 @@ export function onCartLanded(handler: () => void): () => void {
|
||||
/**
|
||||
* Der Hoehepunkt des Einkaufens: ein Tropfen in Wabenform loest sich vom
|
||||
* Knopf, fliegt im Bogen zum Warenkorb und "tropft" hinein. Danach wippt
|
||||
* der Korb, der Zaehler springt, und die Schublade oeffnet sich — Ursache
|
||||
* und Wirkung werden sichtbar verbunden, statt dass die Schublade ohne
|
||||
* Vorwarnung von der Seite hereinschiebt.
|
||||
* der Korb, leuchtet auf, ein kleiner Tropfen laeuft an ihm herunter — und
|
||||
* erst wenn der abgeperlt ist, oeffnet sich die Schublade. Ursache und
|
||||
* Wirkung werden sichtbar verbunden, statt dass die Schublade ohne
|
||||
* Vorwarnung von der Seite hereinschiebt und das Nachspiel verdeckt.
|
||||
*
|
||||
* Reduzierte Bewegung / Symbol nicht sichtbar (z.B. weggescrollter Header
|
||||
* auf kleinen Geraeten): kein Flug, die Schublade oeffnet sofort.
|
||||
@@ -39,9 +50,9 @@ export function CartFlight() {
|
||||
const openCart = useCartStore((s) => s.openCart);
|
||||
|
||||
useEffect(() => {
|
||||
const land = () => {
|
||||
const land = (drawerDelayMs: number) => {
|
||||
window.dispatchEvent(new Event(LAND_EVENT));
|
||||
window.setTimeout(openCart, 180);
|
||||
window.setTimeout(openCart, drawerDelayMs);
|
||||
};
|
||||
|
||||
const onFlight = (event: Event) => {
|
||||
@@ -53,7 +64,7 @@ export function CartFlight() {
|
||||
targetRect && targetRect.width > 0 && targetRect.bottom > 0 && targetRect.top < window.innerHeight;
|
||||
|
||||
if (reduceMotion || !targetRect || !targetVisible) {
|
||||
land();
|
||||
land(DRAWER_WITHOUT_FLIGHT_MS);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -83,11 +94,11 @@ export function CartFlight() {
|
||||
);
|
||||
animation.onfinish = () => {
|
||||
drop.remove();
|
||||
land();
|
||||
land(DRAWER_AFTER_DRIP_MS);
|
||||
};
|
||||
animation.oncancel = () => {
|
||||
drop.remove();
|
||||
land();
|
||||
land(DRAWER_WITHOUT_FLIGHT_MS);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useEffect } from "react";
|
||||
import { motion, useAnimationControls, useReducedMotion } from "motion/react";
|
||||
import { onCartLanded } from "@/components/cart-flight";
|
||||
import { onCartLanded, DRIP_DELAY_S, DRIP_DURATION_S } from "@/components/cart-flight";
|
||||
|
||||
// Der Korb im Kopfzeilen-Symbol (20 px in einem 40-px-Knopf, viewBox 24):
|
||||
// seine Unterkante liegt bei y=15, die Mitte bei x=13.5. Dort bildet sich
|
||||
@@ -10,7 +10,6 @@ import { onCartLanded } from "@/components/cart-flight";
|
||||
const DRIP_LEFT_PX = 10 + (13.5 / 24) * 20;
|
||||
const DRIP_TOP_PX = 10 + (15 / 24) * 20;
|
||||
const DRIP_WIDTH_PX = 6;
|
||||
const DRIP_DELAY_S = 0.3;
|
||||
|
||||
/**
|
||||
* Nachspiel der Landung eines Honigtropfens (components/cart-flight.tsx):
|
||||
@@ -53,7 +52,7 @@ export function CartLandingEffect() {
|
||||
scaleY: [0.2, 1, 1.35, 1, 0.8],
|
||||
y: [0, 0, 3, 13, 17],
|
||||
transition: {
|
||||
duration: 1.1,
|
||||
duration: DRIP_DURATION_S,
|
||||
delay: DRIP_DELAY_S,
|
||||
ease: "easeIn",
|
||||
times: [0, 0.3, 0.55, 0.85, 1],
|
||||
|
||||
Reference in new issue
Block a user