feat(settings): animate buttons

This commit is contained in:
2026-02-10 14:03:40 +01:00
parent f8998206c1
commit d7783d881e
14 changed files with 85 additions and 23 deletions

View File

@@ -192,7 +192,7 @@ onRender((ctx) => {
/> />
<CommonButtons <CommonButtons
:y-offset="confirmationModal.buttonsYOffset" :y-offset="confirmationModal.buttonsYOffset + store.submenuButtonsOffsetY"
:b-label="$t('common.cancel')" :b-label="$t('common.cancel')"
:a-label="$t('common.reset')" :a-label="$t('common.reset')"
@activate-b="handleCancel()" @activate-b="handleCancel()"

View File

@@ -79,7 +79,7 @@ defineOptions({ render: () => null });
/> />
<CommonButtons <CommonButtons
:y-offset="0" :y-offset="store.submenuButtonsOffsetY"
:b-label="$t('common.cancel')" :b-label="$t('common.cancel')"
:a-label="$t('common.confirm')" :a-label="$t('common.confirm')"
@activate-b="handleCancel" @activate-b="handleCancel"

View File

@@ -97,7 +97,7 @@ defineOptions({ render: () => null });
/> />
<CommonButtons <CommonButtons
:y-offset="0" :y-offset="store.submenuButtonsOffsetY"
:b-label="$t('common.cancel')" :b-label="$t('common.cancel')"
:a-label="$t('common.confirm')" :a-label="$t('common.confirm')"
@activate-b="handleCancel" @activate-b="handleCancel"

View File

@@ -331,7 +331,7 @@ const handleActivateB = () => {
/> />
<CommonButtons <CommonButtons
:y-offset="settingsStore.barOffsetY" :y-offset="settingsStore.barOffsetY + settingsStore.submenuButtonsOffsetY"
:b-label="isSubmenuSelected ? $t('common.goBack') : $t('common.quit')" :b-label="isSubmenuSelected ? $t('common.goBack') : $t('common.quit')"
:a-label="$t('common.select')" :a-label="$t('common.select')"
@activate-b="handleActivateB()" @activate-b="handleActivateB()"

View File

@@ -19,6 +19,7 @@ const handleActivateB = () => {
store.closeSubMenu(); store.closeSubMenu();
} }
}, },
keepButtonsDown: (choice) => choice === "confirm",
}); });
}; };
@@ -565,7 +566,7 @@ useKeyDown((key) => {
<template> <template>
<CommonButtons <CommonButtons
:y-offset="confirmationModal.buttonsYOffset" :y-offset="confirmationModal.buttonsYOffset + store.submenuButtonsOffsetY"
:b-label="$t('common.quit')" :b-label="$t('common.quit')"
:a-label="$t('common.restart')" :a-label="$t('common.restart')"
@activate-b="handleActivateB()" @activate-b="handleActivateB()"

View File

@@ -164,6 +164,7 @@ const handleConfirm = () => {
await animateOutro(); await animateOutro();
store.closeSubMenu(); store.closeSubMenu();
}, },
keepButtonsDown: true,
timeout: 2000, timeout: 2000,
}); });
}; };
@@ -202,7 +203,7 @@ defineOptions({
<template> <template>
<CommonButtons <CommonButtons
:y-offset="confirmationModal.buttonsYOffset" :y-offset="confirmationModal.buttonsYOffset + store.submenuButtonsOffsetY"
:b-label="$t('common.cancel')" :b-label="$t('common.cancel')"
:a-label="$t('common.confirm')" :a-label="$t('common.confirm')"
@activate-b="handleCancel" @activate-b="handleCancel"

View File

@@ -110,6 +110,7 @@ const handleConfirm = () => {
await animateOutro(); await animateOutro();
store.closeSubMenu(); store.closeSubMenu();
}, },
keepButtonsDown: true,
timeout: 2000, timeout: 2000,
}); });
}; };
@@ -179,7 +180,7 @@ onRender((ctx) => {
<template> <template>
<CommonButtons <CommonButtons
:y-offset="confirmationModal.buttonsYOffset" :y-offset="confirmationModal.buttonsYOffset + store.submenuButtonsOffsetY"
:b-label="$t('common.cancel')" :b-label="$t('common.cancel')"
:a-label="$t('common.confirm')" :a-label="$t('common.confirm')"
@activate-b="handleCancel" @activate-b="handleCancel"

View File

@@ -138,6 +138,7 @@ const handleActivateB = () => {
state.value = "playing"; state.value = "playing";
} }
}, },
keepButtonsDown: (choice) => choice === "confirm",
}); });
} else { } else {
animateOutro().then(() => store.closeSubMenu()); animateOutro().then(() => store.closeSubMenu());
@@ -238,6 +239,7 @@ const showDeathScreen = () => {
store.closeSubMenu(); store.closeSubMenu();
} }
}, },
keepButtonsDown: (choice) => choice === "cancel",
}); });
}; };
@@ -412,7 +414,7 @@ defineOptions({ render: () => null });
<template> <template>
<CommonButtons <CommonButtons
:y-offset="confirmationModal.buttonsYOffset" :y-offset="confirmationModal.buttonsYOffset + store.submenuButtonsOffsetY"
:b-label="$t('common.quit')" :b-label="$t('common.quit')"
:a-label="state === 'waiting' ? $t('common.start') : $t('common.restart')" :a-label="state === 'waiting' ? $t('common.start') : $t('common.restart')"
@activate-b="handleActivateB" @activate-b="handleActivateB"

View File

@@ -78,6 +78,7 @@ const handleActivateA = () => {
await animateOutro(); await animateOutro();
store.closeSubMenu(); store.closeSubMenu();
}, },
keepButtonsDown: true,
timeout: 2000, timeout: 2000,
}); });
}; };
@@ -111,7 +112,7 @@ defineOptions({ render: () => null });
/> />
<CommonButtons <CommonButtons
:y-offset="confirmationModal.buttonsYOffset" :y-offset="confirmationModal.buttonsYOffset + store.submenuButtonsOffsetY"
:b-label="$t('common.cancel')" :b-label="$t('common.cancel')"
:a-label="$t('common.confirm')" :a-label="$t('common.confirm')"
@activate-b="handleActivateB" @activate-b="handleActivateB"

View File

@@ -278,6 +278,7 @@ const handleActivateA = () => {
await animateOutro(); await animateOutro();
store.closeSubMenu(); store.closeSubMenu();
}, },
keepButtonsDown: true,
timeout: 2000, timeout: 2000,
}); });
}; };
@@ -285,7 +286,7 @@ const handleActivateA = () => {
<template> <template>
<CommonButtons <CommonButtons
:y-offset="confirmationModal.buttonsYOffset" :y-offset="confirmationModal.buttonsYOffset + store.submenuButtonsOffsetY"
:b-label="$t('common.cancel')" :b-label="$t('common.cancel')"
:a-label="$t('common.confirm')" :a-label="$t('common.confirm')"
@activate-b="handleActivateB" @activate-b="handleActivateB"

View File

@@ -101,6 +101,7 @@ const handleCancel = async () => {
onCancel: () => { onCancel: () => {
state.value = "alive"; state.value = "alive";
}, },
keepButtonsDown: (choice) => choice === "confirm",
}); });
break; break;
} }
@@ -327,7 +328,7 @@ defineOptions({ render: () => null });
<template> <template>
<CommonButtons <CommonButtons
:y-offset="confirmationModal.buttonsYOffset" :y-offset="confirmationModal.buttonsYOffset + store.submenuButtonsOffsetY"
:b-label="$t('common.quit')" :b-label="$t('common.quit')"
:a-label="state === 'waiting' ? $t('common.start') : $t('common.restart')" :a-label="state === 'waiting' ? $t('common.start') : $t('common.restart')"
@activate-b="handleCancel" @activate-b="handleCancel"

View File

@@ -127,7 +127,7 @@ defineOptions({ render: () => null });
<template> <template>
<CommonButtons <CommonButtons
:y-offset="0" :y-offset="store.submenuButtonsOffsetY"
:b-label="$t('common.cancel')" :b-label="$t('common.cancel')"
:a-label="$t('common.confirm')" :a-label="$t('common.confirm')"
@activate-b="handleCancel" @activate-b="handleCancel"

View File

@@ -14,6 +14,10 @@ export const useConfirmationModal = defineStore("confirmationModal", {
onConfirm: null as (() => void) | null, onConfirm: null as (() => void) | null,
onCancel: null as (() => void) | null, onCancel: null as (() => void) | null,
onClosed: null as ((choice: "confirm" | "cancel") => void) | null, onClosed: null as ((choice: "confirm" | "cancel") => void) | null,
keepButtonsDown: null as
| boolean
| ((choice: "confirm" | "cancel") => boolean)
| null,
offsetY: MODAL_MAX_Y_OFFSET, offsetY: MODAL_MAX_Y_OFFSET,
buttonsYOffset: 0, buttonsYOffset: 0,
modalButtonsYOffset: BUTTONS_MAX_Y_OFFSET, modalButtonsYOffset: BUTTONS_MAX_Y_OFFSET,
@@ -29,6 +33,7 @@ export const useConfirmationModal = defineStore("confirmationModal", {
onCancel?: () => void; onCancel?: () => void;
onConfirm?: () => void; onConfirm?: () => void;
onClosed?: (choice: "confirm" | "cancel") => void; onClosed?: (choice: "confirm" | "cancel") => void;
keepButtonsDown?: boolean | ((choice: "confirm" | "cancel") => boolean);
timeout?: number; timeout?: number;
}) { }) {
gsap.killTweensOf(this); gsap.killTweensOf(this);
@@ -38,6 +43,7 @@ export const useConfirmationModal = defineStore("confirmationModal", {
this.onConfirm = options.onConfirm ?? null; this.onConfirm = options.onConfirm ?? null;
this.onCancel = options.onCancel ?? null; this.onCancel = options.onCancel ?? null;
this.onClosed = options.onClosed ?? null; this.onClosed = options.onClosed ?? null;
this.keepButtonsDown = options.keepButtonsDown ?? null;
this.isVisible = true; this.isVisible = true;
this.isClosing = false; this.isClosing = false;
this.isOpen = true; this.isOpen = true;
@@ -80,7 +86,12 @@ export const useConfirmationModal = defineStore("confirmationModal", {
this.isClosing = true; this.isClosing = true;
gsap const keepButtonsDown =
typeof this.keepButtonsDown === "function"
? this.keepButtonsDown(choice)
: !!this.keepButtonsDown;
const tl = gsap
.timeline() .timeline()
// modal buttons down // modal buttons down
.to(this, { .to(this, {
@@ -93,18 +104,25 @@ export const useConfirmationModal = defineStore("confirmationModal", {
offsetY: MODAL_MAX_Y_OFFSET, offsetY: MODAL_MAX_Y_OFFSET,
duration: MODAL_TIME, duration: MODAL_TIME,
ease: "none", ease: "none",
}) });
if (!keepButtonsDown) {
// standard buttons up // standard buttons up
.to(this, { tl.to(this, {
buttonsYOffset: 0, buttonsYOffset: 0,
duration: BUTTONS_TIME, duration: BUTTONS_TIME,
ease: "none", ease: "none",
})
.call(() => {
const closedCallback = this.onClosed;
this.$reset();
closedCallback?.(choice);
}); });
}
tl.call(() => {
const closedCallback = this.onClosed;
this.$reset();
if (keepButtonsDown) {
this.buttonsYOffset = BUTTONS_MAX_Y_OFFSET;
}
closedCallback?.(choice);
});
}, },
}, },
}); });

View File

@@ -49,6 +49,8 @@ export const useSettingsStore = defineStore("settings", {
opacity: 0, opacity: 0,
}, },
submenuButtonsOffsetY: 0,
animatingNotification: false, animatingNotification: false,
isIntro: true, isIntro: true,
@@ -77,10 +79,25 @@ export const useSettingsStore = defineStore("settings", {
{ offsetY: 16, opacity: 0 }, { offsetY: 16, opacity: 0 },
{ offsetY: 0, opacity: 1, duration: 0.25, ease: "none" }, { offsetY: 0, opacity: 1, duration: 0.25, ease: "none" },
"+=0.05", "+=0.05",
)
.to(this, {
submenuButtonsOffsetY: 24,
duration: 0.167,
ease: "none",
})
.call(() => {
this.currentSubMenu = submenu;
})
.to(
this,
{
submenuButtonsOffsetY: 0,
duration: 0.167,
ease: "none",
},
"+=0.05",
); );
this.currentSubMenu = submenu;
const achievements = useAchievementsStore(); const achievements = useAchievementsStore();
if (!achievements.advancement.visitedSettings.includes(submenu)) { if (!achievements.advancement.visitedSettings.includes(submenu)) {
achievements.advancement.visitedSettings.push(submenu); achievements.advancement.visitedSettings.push(submenu);
@@ -94,14 +111,33 @@ export const useSettingsStore = defineStore("settings", {
}, },
async closeSubMenu() { async closeSubMenu() {
this.currentSubMenu = null; const confirmationModal = useConfirmationModal();
confirmationModal.buttonsYOffset = 0;
await gsap await gsap
.timeline() .timeline()
.to(this, {
submenuButtonsOffsetY: 24,
duration: 0.167,
ease: "none",
})
.call(() => {
this.currentSubMenu = null;
})
.fromTo( .fromTo(
this.submenuBackground, this.submenuBackground,
{ offsetY: 0, opacity: 1 }, { offsetY: 0, opacity: 1 },
{ offsetY: 16, opacity: 0, duration: 0.25, ease: "none" }, { offsetY: 16, opacity: 0, duration: 0.25, ease: "none" },
0.167,
)
.to(
this,
{
submenuButtonsOffsetY: 0,
duration: 0.167,
ease: "none",
},
0.217,
) )
.fromTo( .fromTo(
this.submenuTransition, this.submenuTransition,