.tools refine hover
This commit is contained in:
@@ -1,16 +1,16 @@
|
|||||||
import { useState } from "react";
|
import { useRef, useState, type RefObject } from "react";
|
||||||
import { HomeIcon } from "@/components/ui/home";
|
import { HomeIcon } from "@/components/ui/home";
|
||||||
import { HistoryIcon } from "@/components/ui/history-icon";
|
import { HistoryIcon } from "@/components/ui/history-icon";
|
||||||
import { SettingsIcon } from "@/components/ui/settings";
|
import { SettingsIcon } from "@/components/ui/settings";
|
||||||
import { ActivityIcon } from "@/components/ui/activity";
|
import { ActivityIcon, type ActivityIconHandle } from "@/components/ui/activity";
|
||||||
import { TerminalIcon } from "@/components/ui/terminal";
|
import { TerminalIcon } from "@/components/ui/terminal";
|
||||||
import { FileMusicIcon } from "@/components/ui/file-music";
|
import { FileMusicIcon, type FileMusicIconHandle } from "@/components/ui/file-music";
|
||||||
import { FilePenIcon } from "@/components/ui/file-pen";
|
import { FilePenIcon, type FilePenIconHandle } from "@/components/ui/file-pen";
|
||||||
import { CoffeeIcon } from "@/components/ui/coffee";
|
import { CoffeeIcon } from "@/components/ui/coffee";
|
||||||
import { BadgeAlertIcon } from "@/components/ui/badge-alert";
|
import { BadgeAlertIcon } from "@/components/ui/badge-alert";
|
||||||
import { GithubIcon } from "@/components/ui/github";
|
import { GithubIcon } from "@/components/ui/github";
|
||||||
import { BlocksIcon } from "@/components/ui/blocks-icon";
|
import { BlocksIcon } from "@/components/ui/blocks-icon";
|
||||||
import { AudioLinesIcon } from "@/components/ui/audio-lines";
|
import { AudioLinesIcon, type AudioLinesIconHandle } from "@/components/ui/audio-lines";
|
||||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
||||||
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
@@ -23,9 +23,19 @@ interface SidebarProps {
|
|||||||
currentPage: PageType;
|
currentPage: PageType;
|
||||||
onPageChange: (page: PageType) => void;
|
onPageChange: (page: PageType) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface AnimatedIconHandle {
|
||||||
|
startAnimation: () => void;
|
||||||
|
stopAnimation: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
export function Sidebar({ currentPage, onPageChange }: SidebarProps) {
|
export function Sidebar({ currentPage, onPageChange }: SidebarProps) {
|
||||||
const [isIssuesDialogOpen, setIsIssuesDialogOpen] = useState(false);
|
const [isIssuesDialogOpen, setIsIssuesDialogOpen] = useState(false);
|
||||||
const [hasIssueAgreement, setHasIssueAgreement] = useState(false);
|
const [hasIssueAgreement, setHasIssueAgreement] = useState(false);
|
||||||
|
const analyzerIconRef = useRef<ActivityIconHandle>(null);
|
||||||
|
const converterIconRef = useRef<FileMusicIconHandle>(null);
|
||||||
|
const resamplerIconRef = useRef<AudioLinesIconHandle>(null);
|
||||||
|
const fileManagerIconRef = useRef<FilePenIconHandle>(null);
|
||||||
const handleIssuesDialogChange = (open: boolean) => {
|
const handleIssuesDialogChange = (open: boolean) => {
|
||||||
setIsIssuesDialogOpen(open);
|
setIsIssuesDialogOpen(open);
|
||||||
if (!open) {
|
if (!open) {
|
||||||
@@ -36,6 +46,12 @@ export function Sidebar({ currentPage, onPageChange }: SidebarProps) {
|
|||||||
openExternal("https://github.com/afkarxyz/SpotiFLAC/issues");
|
openExternal("https://github.com/afkarxyz/SpotiFLAC/issues");
|
||||||
handleIssuesDialogChange(false);
|
handleIssuesDialogChange(false);
|
||||||
};
|
};
|
||||||
|
const getAnimatedItemHandlers = <T extends AnimatedIconHandle>(iconRef: RefObject<T | null>) => ({
|
||||||
|
onMouseEnter: () => iconRef.current?.startAnimation(),
|
||||||
|
onMouseLeave: () => iconRef.current?.stopAnimation(),
|
||||||
|
onFocus: () => iconRef.current?.startAnimation(),
|
||||||
|
onBlur: () => iconRef.current?.stopAnimation(),
|
||||||
|
});
|
||||||
return (<div className="fixed left-0 top-0 h-full w-14 bg-card border-r border-border flex flex-col items-center py-14 z-30">
|
return (<div className="fixed left-0 top-0 h-full w-14 bg-card border-r border-border flex flex-col items-center py-14 z-30">
|
||||||
<div className="flex flex-col gap-2 flex-1">
|
<div className="flex flex-col gap-2 flex-1">
|
||||||
<Tooltip delayDuration={0}>
|
<Tooltip delayDuration={0}>
|
||||||
@@ -96,20 +112,20 @@ export function Sidebar({ currentPage, onPageChange }: SidebarProps) {
|
|||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<DropdownMenuContent side="right" sideOffset={14} className="min-w-[200px] ml-2">
|
<DropdownMenuContent side="right" sideOffset={14} className="min-w-[200px] ml-2">
|
||||||
<DropdownMenuItem onClick={() => onPageChange("audio-analysis")} className="gap-3 cursor-pointer py-2 px-3">
|
<DropdownMenuItem onClick={() => onPageChange("audio-analysis")} className="gap-3 cursor-pointer py-2 px-3" {...getAnimatedItemHandlers(analyzerIconRef)}>
|
||||||
<ActivityIcon size={16}/>
|
<ActivityIcon ref={analyzerIconRef} size={16}/>
|
||||||
<span>Audio Quality Analyzer</span>
|
<span>Audio Quality Analyzer</span>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem onClick={() => onPageChange("audio-converter")} className="gap-3 cursor-pointer py-2 px-3">
|
<DropdownMenuItem onClick={() => onPageChange("audio-converter")} className="gap-3 cursor-pointer py-2 px-3" {...getAnimatedItemHandlers(converterIconRef)}>
|
||||||
<FileMusicIcon size={16}/>
|
<FileMusicIcon ref={converterIconRef} size={16}/>
|
||||||
<span>Audio Converter</span>
|
<span>Audio Converter</span>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem onClick={() => onPageChange("audio-resampler")} className="gap-3 cursor-pointer py-2 px-3">
|
<DropdownMenuItem onClick={() => onPageChange("audio-resampler")} className="gap-3 cursor-pointer py-2 px-3" {...getAnimatedItemHandlers(resamplerIconRef)}>
|
||||||
<AudioLinesIcon size={16}/>
|
<AudioLinesIcon ref={resamplerIconRef} size={16}/>
|
||||||
<span>Audio Resampler</span>
|
<span>Audio Resampler</span>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem onClick={() => onPageChange("file-manager")} className="gap-3 cursor-pointer py-2 px-3">
|
<DropdownMenuItem onClick={() => onPageChange("file-manager")} className="gap-3 cursor-pointer py-2 px-3" {...getAnimatedItemHandlers(fileManagerIconRef)}>
|
||||||
<FilePenIcon size={16}/>
|
<FilePenIcon ref={fileManagerIconRef} size={16}/>
|
||||||
<span>File Manager</span>
|
<span>File Manager</span>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
|
|||||||
Reference in New Issue
Block a user