feat: Add smooth transitions and animations to UI
- Add fade-in/fade-out transition to command palette (200ms) - Add scale animation to command palette on open/close - Add smooth popup animation to context menu (150ms) - Add visual feedback for file selection with ring effect - Add hover scale effect to file grid items - Add transition-all to list view items for consistent behavior - Zero JavaScript overhead, pure CSS transitions - All animations under 200ms for instant feel
This commit is contained in:
@@ -226,13 +226,17 @@ export function CommandPalette({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed inset-0 z-50 flex items-center justify-center bg-black/30",
|
"fixed inset-0 z-50 flex items-center justify-center bg-black/30 transition-opacity duration-200",
|
||||||
!isOpen && "hidden",
|
!isOpen && "opacity-0 pointer-events-none",
|
||||||
)}
|
)}
|
||||||
onClick={() => setIsOpen(false)}
|
onClick={() => setIsOpen(false)}
|
||||||
>
|
>
|
||||||
<Command
|
<Command
|
||||||
className="w-3/4 max-w-2xl max-h-[60vh] rounded-lg border-2 border-dark-border shadow-md flex flex-col"
|
className={cn(
|
||||||
|
"w-3/4 max-w-2xl max-h-[60vh] rounded-lg border-2 border-dark-border shadow-md flex flex-col",
|
||||||
|
"transition-all duration-200 ease-out",
|
||||||
|
!isOpen && "scale-95 opacity-0",
|
||||||
|
)}
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<CommandInput
|
<CommandInput
|
||||||
|
|||||||
@@ -102,9 +102,15 @@ export function FileManagerContextMenu({
|
|||||||
}: ContextMenuProps) {
|
}: ContextMenuProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [menuPosition, setMenuPosition] = useState({ x, y });
|
const [menuPosition, setMenuPosition] = useState({ x, y });
|
||||||
|
const [isMounted, setIsMounted] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isVisible) return;
|
if (!isVisible) {
|
||||||
|
setIsMounted(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsMounted(true);
|
||||||
|
|
||||||
const adjustPosition = () => {
|
const adjustPosition = () => {
|
||||||
const menuWidth = 200;
|
const menuWidth = 200;
|
||||||
@@ -183,8 +189,6 @@ export function FileManagerContextMenu({
|
|||||||
};
|
};
|
||||||
}, [isVisible, x, y, onClose]);
|
}, [isVisible, x, y, onClose]);
|
||||||
|
|
||||||
if (!isVisible) return null;
|
|
||||||
|
|
||||||
const isFileContext = files.length > 0;
|
const isFileContext = files.length > 0;
|
||||||
const isSingleFile = files.length === 1;
|
const isSingleFile = files.length === 1;
|
||||||
const isMultipleFiles = files.length > 1;
|
const isMultipleFiles = files.length > 1;
|
||||||
@@ -440,13 +444,24 @@ export function FileManagerContextMenu({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!isVisible && !isMounted) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="fixed inset-0 z-[99990]" />
|
<div
|
||||||
|
className={cn(
|
||||||
|
"fixed inset-0 z-[99990] transition-opacity duration-150",
|
||||||
|
!isMounted && "opacity-0"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
data-context-menu
|
data-context-menu
|
||||||
className="fixed bg-dark-bg border border-dark-border rounded-lg shadow-xl min-w-[180px] max-w-[250px] z-[99995] overflow-hidden"
|
className={cn(
|
||||||
|
"fixed bg-dark-bg border border-dark-border rounded-lg shadow-xl min-w-[180px] max-w-[250px] z-[99995] overflow-hidden",
|
||||||
|
"transition-all duration-150 ease-out origin-top-left",
|
||||||
|
isMounted ? "opacity-100 scale-100" : "opacity-0 scale-95"
|
||||||
|
)}
|
||||||
style={{
|
style={{
|
||||||
left: menuPosition.x,
|
left: menuPosition.x,
|
||||||
top: menuPosition.y,
|
top: menuPosition.y,
|
||||||
|
|||||||
@@ -1049,8 +1049,9 @@ export function FileManagerGrid({
|
|||||||
draggable={true}
|
draggable={true}
|
||||||
className={cn(
|
className={cn(
|
||||||
"group p-3 rounded-lg cursor-pointer",
|
"group p-3 rounded-lg cursor-pointer",
|
||||||
"hover:bg-accent hover:text-accent-foreground border-2 border-transparent",
|
"transition-all duration-150 ease-out",
|
||||||
isSelected && "bg-primary/20 border-primary",
|
"hover:bg-accent hover:text-accent-foreground hover:scale-[1.02] border-2 border-transparent",
|
||||||
|
isSelected && "bg-primary/20 border-primary ring-2 ring-primary/20",
|
||||||
dragState.target?.path === file.path &&
|
dragState.target?.path === file.path &&
|
||||||
"bg-muted border-primary border-dashed relative z-10",
|
"bg-muted border-primary border-dashed relative z-10",
|
||||||
dragState.files.some((f) => f.path === file.path) &&
|
dragState.files.some((f) => f.path === file.path) &&
|
||||||
@@ -1138,8 +1139,9 @@ export function FileManagerGrid({
|
|||||||
draggable={true}
|
draggable={true}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex items-center gap-3 p-2 rounded cursor-pointer",
|
"flex items-center gap-3 p-2 rounded cursor-pointer",
|
||||||
|
"transition-all duration-150 ease-out",
|
||||||
"hover:bg-accent hover:text-accent-foreground",
|
"hover:bg-accent hover:text-accent-foreground",
|
||||||
isSelected && "bg-primary/20",
|
isSelected && "bg-primary/20 ring-2 ring-primary/20",
|
||||||
dragState.target?.path === file.path &&
|
dragState.target?.path === file.path &&
|
||||||
"bg-muted border-primary border-dashed relative z-10",
|
"bg-muted border-primary border-dashed relative z-10",
|
||||||
dragState.files.some((f) => f.path === file.path) &&
|
dragState.files.some((f) => f.path === file.path) &&
|
||||||
|
|||||||
Reference in New Issue
Block a user