mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-08-04 11:43:57 +08:00
feat(ui): add exit animation to FullScreenPanel dialogs
- Wrap FullScreenPanel content with AnimatePresence for exit animation
- Add exit={{ opacity: 0 }} to enable fade-out on close
- Use useRef + useEffect to preserve provider data during exit animation
- Follow React best practices by updating refs in useEffect instead of render
Affected components:
- EditProviderDialog
- UsageScriptModal
- AddProviderDialog
- McpFormModal
- ProxySettingsDialog
This commit is contained in:
+21
-3
@@ -65,6 +65,22 @@ function App() {
|
||||
const [envConflicts, setEnvConflicts] = useState<EnvConflict[]>([]);
|
||||
const [showEnvBanner, setShowEnvBanner] = useState(false);
|
||||
|
||||
// 保存最后一个有效的 provider,用于动画退出期间显示内容
|
||||
const lastUsageProviderRef = useRef<Provider | null>(null);
|
||||
const lastEditingProviderRef = useRef<Provider | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (usageProvider) {
|
||||
lastUsageProviderRef.current = usageProvider;
|
||||
}
|
||||
}, [usageProvider]);
|
||||
|
||||
useEffect(() => {
|
||||
if (editingProvider) {
|
||||
lastEditingProviderRef.current = editingProvider;
|
||||
}
|
||||
}, [editingProvider]);
|
||||
|
||||
const promptPanelRef = useRef<any>(null);
|
||||
const mcpPanelRef = useRef<any>(null);
|
||||
const skillsPageRef = useRef<any>(null);
|
||||
@@ -639,7 +655,7 @@ function App() {
|
||||
|
||||
<EditProviderDialog
|
||||
open={Boolean(editingProvider)}
|
||||
provider={editingProvider}
|
||||
provider={lastEditingProviderRef.current}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) {
|
||||
setEditingProvider(null);
|
||||
@@ -650,14 +666,16 @@ function App() {
|
||||
isProxyTakeover={isProxyRunning && isCurrentAppTakeoverActive}
|
||||
/>
|
||||
|
||||
{usageProvider && (
|
||||
{lastUsageProviderRef.current && (
|
||||
<UsageScriptModal
|
||||
provider={usageProvider}
|
||||
provider={lastUsageProviderRef.current}
|
||||
appId={activeApp}
|
||||
isOpen={Boolean(usageProvider)}
|
||||
onClose={() => setUsageProvider(null)}
|
||||
onSave={(script) => {
|
||||
if (usageProvider) {
|
||||
void saveUsageScript(usageProvider, script);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { motion } from "framer-motion";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { ArrowLeft } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
@@ -33,12 +33,13 @@ export const FullScreenPanel: React.FC<FullScreenPanelProps> = ({
|
||||
};
|
||||
}, [isOpen]);
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
return createPortal(
|
||||
<AnimatePresence>
|
||||
{isOpen && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
className="fixed inset-0 z-[60] flex flex-col"
|
||||
style={{ backgroundColor: "hsl(var(--background))" }}
|
||||
@@ -75,7 +76,9 @@ export const FullScreenPanel: React.FC<FullScreenPanelProps> = ({
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</motion.div>,
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>,
|
||||
document.body,
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user