From 3b0dad754fe60ed609dc40661b5269b74aa07043 Mon Sep 17 00:00:00 2001
From: razeprasine
Date: Thu, 25 Jun 2026 06:30:19 +0100
Subject: [PATCH] fixes issue 943
---
fix.md | 32 ++-
.../src/components/MultisigApprovalModal.tsx | 244 +++++++++++-------
2 files changed, 172 insertions(+), 104 deletions(-)
diff --git a/fix.md b/fix.md
index 1d14199c..0a3ed661 100644
--- a/fix.md
+++ b/fix.md
@@ -1,20 +1,28 @@
-[Backend] Enhance error recovery for Audit Logger
-
+[Frontend] Implement framer-motion animations for Multi-sig Approval Modal
+Repo Avatar
+emdevelopa/Stellar_Payment_API
Description
-This task involves system optimization for the Audit Logger module.
-The goal is to Enhance error recovery for.lower Audit Logger to enhance the platform's robustness and user experience.
+This task involves UX enhancement for the Multi-sig Approval Modal module.
+The goal is to implement framer-motion animations for Multi-sig Approval Modal to improve the platform's styling, user interactions, and overall accessibility.
Requirements and context
-Adhere to the Drips Wave design and engineering standards.
-Ensure full test coverage for new logic.
-Must be secure, performant, and well-documented.
-Specifically focused on system optimization.
+Must be secure, tested, and documented
+Adhere to the Drips Wave design and UI/UX standards
+Ensure compatibility across desktop and mobile browsers
+Specifically focused on frontend UX enhancement and responsiveness
Suggested execution
Fork the repo and create a branch
-Review existing implementation in Audit Logger.
-Apply changes: Enhance error recovery for.
+git checkout -b feature/fe-implement-framer-motion-animations-for-multi-sig-approval-modal
+Implement changes
+
+Review existing component in Multi-sig Approval Modal
+Apply changes: Implement framer-motion animations for Multi-sig Approval Modal
+Use clean CSS or tailwind variables for styling
+Maintain state transitions and visual feedback
Test and commit
-Example commit message
-backend: Enhance error recovery for Audit Logger
\ No newline at end of file
+
+Test mobile responsiveness and interactive states
+Check accessibility (a11y) using standard audits
+Include screenshots or gifs in the PR
diff --git a/frontend/src/components/MultisigApprovalModal.tsx b/frontend/src/components/MultisigApprovalModal.tsx
index 536b7125..cc3901ae 100644
--- a/frontend/src/components/MultisigApprovalModal.tsx
+++ b/frontend/src/components/MultisigApprovalModal.tsx
@@ -1,10 +1,57 @@
"use client";
-import { useCallback, useEffect, useRef, useState } from "react";
-import { motion, AnimatePresence } from "framer-motion";
+import { useCallback, useEffect, useRef } from "react";
+import { motion, AnimatePresence, useReducedMotion } from "framer-motion";
import { useMultisigState, useMultisigActions } from "@/lib/multisig-context";
import { toast } from "sonner";
import { CopyButton } from "@/components/CopyButton";
+import {
+ errorMessageVariants,
+} from "@/lib/network-animations";
+
+const backdropVariants = {
+ hidden: { opacity: 0 },
+ visible: { opacity: 1 },
+ exit: { opacity: 0, transition: { duration: 0.3 } },
+};
+
+const modalVariants = {
+ hidden: { scale: 0.85, opacity: 0, y: 30 },
+ visible: {
+ scale: 1,
+ opacity: 1,
+ y: 0,
+ transition: {
+ duration: 0.4,
+ ease: [0.32, 0.72, 0.0, 1.0],
+ type: "spring",
+ stiffness: 300,
+ damping: 30,
+ },
+ },
+ exit: {
+ scale: 0.85,
+ opacity: 0,
+ y: 30,
+ transition: { duration: 0.2, ease: [0.32, 0.72, 0.0, 1.0] },
+ },
+};
+
+const stepVariants = {
+ hidden: { opacity: 0, y: 10 },
+ visible: { opacity: 1, y: 0, transition: { duration: 0.2 } },
+ exit: { opacity: 0, y: -10, transition: { duration: 0.15 } },
+};
+
+const signerListVariants = {
+ hidden: {},
+ visible: { transition: { staggerChildren: 0.05 } },
+};
+
+const signerItemVariants = {
+ hidden: { opacity: 0, x: -10 },
+ visible: { opacity: 1, x: 0, transition: { duration: 0.2 } },
+};
interface MultisigApprovalModalProps {
readonly isOpen: boolean;
@@ -19,8 +66,7 @@ export default function MultisigApprovalModal({
networkPassphrase,
transaction: initialTransaction,
}: MultisigApprovalModalProps) {
- const [mounted, setMounted] = useState(false);
- const [visible, setVisible] = useState(false);
+ const prefersReducedMotion = useReducedMotion();
const modalRef = useRef(null);
const {
@@ -47,20 +93,6 @@ export default function MultisigApprovalModal({
retryAction,
} = useMultisigActions();
- // Handle modal visibility animations
- useEffect(() => {
- if (isOpen) {
- setMounted(true);
- requestAnimationFrame(() => {
- requestAnimationFrame(() => setVisible(true));
- });
- } else {
- setVisible(false);
- const timer = setTimeout(() => setMounted(false), 300);
- return () => clearTimeout(timer);
- }
- }, [isOpen]);
-
// Set transaction when modal opens
useEffect(() => {
if (isOpen && initialTransaction && !transaction) {
@@ -70,7 +102,7 @@ export default function MultisigApprovalModal({
// Handle escape key and focus management
useEffect(() => {
- if (!isOpen || !visible) return;
+ if (!isOpen) return;
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === "Escape") {
@@ -82,7 +114,7 @@ export default function MultisigApprovalModal({
modalRef.current?.focus();
return () => document.removeEventListener("keydown", handleKeyDown);
- }, [isOpen, visible]);
+ }, [isOpen]);
// Body scroll lock
useEffect(() => {
@@ -167,28 +199,38 @@ export default function MultisigApprovalModal({
{Math.round(progress)}%
-
+
+
+
{/* Signers List */}
Signers
-
+
{transaction.signers.map((signer) => (
- -
-
-
+
+
))}
-
+
{/* Time Remaining */}
@@ -245,13 +289,15 @@ export default function MultisigApprovalModal({
{/* Submit Button */}
{canSubmit && (
-
+
)}
)}
@@ -295,12 +341,14 @@ export default function MultisigApprovalModal({
)}
-
+
);
@@ -318,18 +366,22 @@ export default function MultisigApprovalModal({
-
-
+
);
@@ -349,18 +401,16 @@ export default function MultisigApprovalModal({
}
};
- if (!mounted) return null;
-
return (
{isOpen && (
{/* Backdrop */}
@@ -368,16 +418,10 @@ export default function MultisigApprovalModal({
{/* Modal */}
-
+
{/* Content */}
@@ -412,10 +458,10 @@ export default function MultisigApprovalModal({
className="p-6 max-h-[70vh] overflow-y-auto"
aria-live="polite"
key={currentStep}
- initial={{ opacity: 0, y: 10 }}
- animate={{ opacity: 1, y: 0 }}
- exit={{ opacity: 0, y: -10 }}
- transition={{ duration: 0.2 }}
+ variants={stepVariants}
+ initial="hidden"
+ animate="visible"
+ exit="exit"
>
{isExpired ? (
@@ -430,12 +476,14 @@ export default function MultisigApprovalModal({
This transaction has expired and can no longer be signed or submitted.
-
+
) : (
renderStep()
@@ -443,28 +491,40 @@ export default function MultisigApprovalModal({
{/* Error Display */}
- {error && currentStep !== "error" && (
-
-
-
-
-
- )}
+
+
+
+
+
+
+ )}
+
)}