Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modal animation #705

Closed
babalicious-io opened this issue Feb 20, 2025 · 3 comments · May be fixed by #706
Closed

Modal animation #705

babalicious-io opened this issue Feb 20, 2025 · 3 comments · May be fixed by #706
Assignees
Labels
enhancement New feature or request help wanted Extra attention is needed
Milestone

Comments

@babalicious-io
Copy link
Collaborator

babalicious-io commented Feb 20, 2025

Modal Animation System: Centralized Management & Consistent Animations

Overview

Need to implement consistent open/close animations for all modals in the application:

  • StampSearch modal (⌘+S in /stamp routes)
  • SRC20Search modal (⌘+S in /src20 routes)
  • Wallet modal
  • Filter modals (F key in respective routes)

Current State

  • Can implement open animations successfully
  • Close animations are problematic due to state management timing
  • Multiple components managing their own modal states leads to inconsistent behavior

Attempted Solutions

1. Component-level Animation State

typescript

const [isClosing, setIsClosing] = useState(false);
const handleClose = () => {
setIsClosing(true);
setTimeout(() => {
onClose();
setIsClosing(false);
}, 400);
};

Issues:

  • State gets cleared before animation completes
  • Unmounting during animation causes memory leaks
  • Inconsistent timing across components

2. Parent Component Management

typescript

const [isModalClosing, setIsModalClosing] = useState(false);
const closeModal = () => {
setIsModalClosing(true);
setTimeout(() => setIsOpen(false), 400);
};

Issues:

  • Props drilling
  • Difficult to coordinate between different modal types
  • Inconsistent behavior with keyboard shortcuts

Proposed Solution

1. Centralize Modal Management in _app.tsx

typescript

interface AppState {
modal: {
isOpen: boolean;
type: "stamp-search" | "src20-search" | "wallet" | null;
isClosing: boolean;
};
}

2. Modal-Specific Animations

Search Modals (StampSearch & SRC20Search)

Open Animation:

  • Fade in backdrop: opacity-0opacity-100 (duration: 100ms)
  • Slide down content: translate-y-[-30px] opacity-0translate-y-0 opacity-100 (duration: 300ms, delay: 100ms)
  • Focus input field after animation completes

Close Animation:

  • Slide up content: translate-y-0 opacity-100translate-y-[-30px] opacity-0 (duration: 300ms)
  • Fade out backdrop: opacity-100opacity-0 (duration: 100ms, delay: 300ms)
  • Cleanup after animation (400ms total)

Wallet Modal

Open Animation:

  • Fade in backdrop: opacity-0opacity-100 (duration: 100ms)
  • Slide up content: translate-y-[30px] opacity-0translate-y-0 opacity-100 (duration: 300ms, delay: 100ms)
  • Focus first interactive element after animation

Close Animation:

  • Slide down content: translate-y-0 opacity-100translate-y-[30px] opacity-0 (duration: 300ms)
  • Fade out backdrop: opacity-100opacity-0 (duration: 100ms, delay: 300ms)
  • Cleanup after animation (400ms total)

3. Implementation Example

typescript

// ModalContainer.tsx
export function ModalContainer({ type, isClosing }: ModalContainerProps) {
const modalBgTop = fixed inset-0 z-50 flex items-start justify-center bg-black/70 backdrop-blur-md overflow-y-auto transition-opacity duration-100 ${isClosing ? "opacity-0 delay-300" : "opacity-100"} ;
const getModalAnimation = () => {
switch (type) {
case "stamp-search":
case "src20-search":
return {
initial: "translate-y-[-30px] opacity-0",
open: "translate-y-0 opacity-100 delay-100",
closing: "translate-y-[-30px] opacity-0 duration-300"
};
case "wallet":
return {
initial: "translate-y-[30px] opacity-0",
open: "translate-y-0 opacity-100 delay-100",
closing: "translate-y-[30px] opacity-0 duration-300"
};
}
};
const { initial, open, closing } = getModalAnimation();
const modalContentClass = transition-all duration-300 ${isClosing ? closing : open} ;
return (
<div class={modalBgTop}>
<div class={modalContentClass}>
{renderContent()}
</div>
</div>
);
}

// app.tsx
export const closeModal = () => {
appState.value = {
...appState.value,
modal: {
...appState.value.modal,
isClosing: true,
},
};
setTimeout(() => {
appState.value = {
...appState.value,
modal: {
isOpen: false,
type: null,
isClosing: false,
},
};
}, 400); // Total animation duration
};

Benefits

  1. Consistent animations across all modals
  2. Centralized state management prevents timing issues
  3. Proper cleanup after animations complete
  4. Unified keyboard shortcut system
  5. Type-safe modal management
  6. Easier to maintain and extend

Next Steps

  1. Implement ModalContainer with animation types
  2. Update existing modals to use new system
  3. Add keyboard shortcut handling in _app.tsx
  4. Test all animation sequences
  5. Document modal types and shortcuts

Questions

  • Should Filter modals use the same animation system?
  • Do we need to handle multiple modals (stacking)?
  • Should we add loading states during transitions?
@babalicious-io
Copy link
Collaborator Author

Another suggestion for filter logic - _app.tsx

interface AppState {
  modal: {
    isOpen: boolean;
    type: "stamp-search" | "src20-search" | "wallet" | null;
    data?: Record<string, unknown>;
    isClosing?: boolean;
  };
  filter: {
    isOpen: boolean;
    type: "stamp" | "src20" | "wallet" | "collection" | null;
  };
  currentRoute: string;
}

@babalicious-io
Copy link
Collaborator Author

I looked into different ways of animating (js libraries/config css styling) and believe the above approach with using tailwind css should be the simplest/fastest.

@babalicious-io babalicious-io added this to the v1 milestone Feb 22, 2025
@babalicious-io babalicious-io linked a pull request Feb 22, 2025 that will close this issue
@babalicious-io babalicious-io added bug Something isn't working enhancement New feature or request help wanted Extra attention is needed and removed bug Something isn't working labels Feb 22, 2025
@babalicious-io
Copy link
Collaborator Author

FYI - the mobile menu open and close animates, but doesn't seem to unmount on close as the other modals.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants