feat(buttonNavigation): block any interactions while the selector is being animated
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
import gsap from "gsap";
|
import gsap from "gsap";
|
||||||
|
|
||||||
|
const SELECTOR_SPEED = 500;
|
||||||
|
|
||||||
export const useButtonNavigation = <T extends Record<string, Rect>>({
|
export const useButtonNavigation = <T extends Record<string, Rect>>({
|
||||||
buttons,
|
buttons,
|
||||||
initialButton,
|
initialButton,
|
||||||
@@ -29,6 +31,11 @@ export const useButtonNavigation = <T extends Record<string, Rect>>({
|
|||||||
const selectedButton = ref(initialButton);
|
const selectedButton = ref(initialButton);
|
||||||
const selectorPosition = ref<Rect>(buttons[initialButton]!);
|
const selectorPosition = ref<Rect>(buttons[initialButton]!);
|
||||||
const nextButton = ref<Entry | undefined>();
|
const nextButton = ref<Entry | undefined>();
|
||||||
|
const isAnimating = ref(false);
|
||||||
|
|
||||||
|
const blockInteractions = computed(
|
||||||
|
() => confirmationModal.isOpen || disabled?.value || isAnimating.value,
|
||||||
|
);
|
||||||
|
|
||||||
const getNavigationTarget = (
|
const getNavigationTarget = (
|
||||||
value: Entry | [buttonName: Entry, blocked: boolean] | undefined,
|
value: Entry | [buttonName: Entry, blocked: boolean] | undefined,
|
||||||
@@ -149,10 +156,14 @@ export const useButtonNavigation = <T extends Record<string, Rect>>({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const animateToButton = (targetButton: Entry, path?: Array<Entry> | null) => {
|
const animateToButton = (targetButton: Entry, path?: Array<Entry> | null) => {
|
||||||
const SPEED = 400;
|
|
||||||
const pathButtons = path && path.length > 0 ? path : [targetButton];
|
const pathButtons = path && path.length > 0 ? path : [targetButton];
|
||||||
|
|
||||||
const timeline = gsap.timeline();
|
isAnimating.value = true;
|
||||||
|
const timeline = gsap.timeline({
|
||||||
|
onComplete: () => {
|
||||||
|
isAnimating.value = false;
|
||||||
|
},
|
||||||
|
});
|
||||||
let prevRect = selectorPosition.value;
|
let prevRect = selectorPosition.value;
|
||||||
|
|
||||||
selectorPosition.value = [...selectorPosition.value];
|
selectorPosition.value = [...selectorPosition.value];
|
||||||
@@ -160,7 +171,7 @@ export const useButtonNavigation = <T extends Record<string, Rect>>({
|
|||||||
for (const button of pathButtons) {
|
for (const button of pathButtons) {
|
||||||
const buttonRect = buttons[button]!;
|
const buttonRect = buttons[button]!;
|
||||||
const distance = calculateDistance(prevRect, buttonRect);
|
const distance = calculateDistance(prevRect, buttonRect);
|
||||||
const duration = distance / SPEED;
|
const duration = distance / SELECTOR_SPEED;
|
||||||
|
|
||||||
timeline.to(
|
timeline.to(
|
||||||
selectorPosition.value,
|
selectorPosition.value,
|
||||||
@@ -184,7 +195,7 @@ export const useButtonNavigation = <T extends Record<string, Rect>>({
|
|||||||
const { onClick } = useScreen();
|
const { onClick } = useScreen();
|
||||||
|
|
||||||
onClick((x: number, y: number) => {
|
onClick((x: number, y: number) => {
|
||||||
if (confirmationModal.isOpen || disabled?.value) return;
|
if (blockInteractions.value) return;
|
||||||
|
|
||||||
for (const [buttonName, buttonRect] of Object.entries(buttons) as [
|
for (const [buttonName, buttonRect] of Object.entries(buttons) as [
|
||||||
Entry,
|
Entry,
|
||||||
@@ -214,7 +225,7 @@ export const useButtonNavigation = <T extends Record<string, Rect>>({
|
|||||||
});
|
});
|
||||||
|
|
||||||
useKeyDown((key) => {
|
useKeyDown((key) => {
|
||||||
if (confirmationModal.isOpen || disabled?.value) return;
|
if (blockInteractions.value) return;
|
||||||
|
|
||||||
const currentButton = selectedButton.value as Entry;
|
const currentButton = selectedButton.value as Entry;
|
||||||
const currentNav = navigation[currentButton];
|
const currentNav = navigation[currentButton];
|
||||||
|
|||||||
Reference in New Issue
Block a user