feat: animate account avatar to close icon

This commit is contained in:
Stavros
2026-06-25 17:30:54 +03:00
parent 93f882e460
commit 0097ecc796
@@ -25,6 +25,7 @@ import {
Palette, Palette,
Settings, Settings,
Sun, Sun,
X,
} from "lucide-react"; } from "lucide-react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useLocation } from "react-router"; import { useLocation } from "react-router";
@@ -45,13 +46,17 @@ import { PocketIDIcon } from "../icons/pocket-id";
import { LocalAuthIcon } from "../icons/local-auth"; import { LocalAuthIcon } from "../icons/local-auth";
import { OAuthIcon } from "../icons/oauth"; import { OAuthIcon } from "../icons/oauth";
function Avatar({ initial }: { initial: string }) { function Avatar({ initial, isOpen }: { initial: string; isOpen: boolean }) {
return ( return (
<span className="group relative grid size-10 place-items-center rounded-full"> <span className="group relative grid size-10 place-items-center rounded-full">
<span className="absolute inset-0 overflow-hidden rounded-full bg-linear-to-b from-neutral-50 to-neutral-100 dark:from-neutral-700 dark:to-neutral-950 shadow-lg"></span> <span className="absolute inset-0 overflow-hidden rounded-full bg-linear-to-b from-neutral-50 to-neutral-100 dark:from-neutral-700 dark:to-neutral-950 shadow-lg"></span>
<span className="relative text-sm font-semibold text-primary"> {isOpen ? (
<X className="relative size-4 text-primary rotate-0 transition-transform duration-200 starting:rotate-45" />
) : (
<span className="relative text-sm font-semibold text-primary rotate-0 transition-transform duration-200 starting:-rotate-45">
{initial} {initial}
</span> </span>
)}
</span> </span>
); );
} }
@@ -81,6 +86,8 @@ export const QuickActions = () => {
const screenParams = useScreenParams(searchParams); const screenParams = useScreenParams(searchParams);
const compiledParams = recompileScreenParams(screenParams); const compiledParams = recompileScreenParams(screenParams);
const [isOpen, setIsOpen] = useState(false);
const providerDetails = ((): const providerDetails = (():
| { name: string; icon: React.ReactNode } | { name: string; icon: React.ReactNode }
| undefined => { | undefined => {
@@ -159,14 +166,14 @@ export const QuickActions = () => {
] as const; ] as const;
return ( return (
<DropdownMenu> <DropdownMenu onOpenChange={(open) => setIsOpen(open)} open={isOpen}>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<button <button
aria-label={t("quickActionsTitle")} aria-label={t("quickActionsTitle")}
className="rounded-full transition-transform duration-200 will-change-transform hover:scale-105 hover:cursor-pointer focus:ring-0 focus:outline-3 focus:outline-ring/50" className="rounded-full transition-transform duration-200 will-change-transform hover:scale-105 hover:cursor-pointer focus:ring-0 focus:outline-3 focus:outline-ring/50"
> >
{auth.authenticated ? ( {auth.authenticated ? (
<Avatar initial={initial!} /> <Avatar initial={initial!} isOpen={isOpen} />
) : ( ) : (
<span className="bg-card text-primary border-border size-10 flex items-center justify-center rounded-full border shadow-lg"> <span className="bg-card text-primary border-border size-10 flex items-center justify-center rounded-full border shadow-lg">
<Settings className="size-4" /> <Settings className="size-4" />