11import { type ReactNode , type FC , useState , type MouseEvent , useRef } from 'react'
22import { SettingsIcon , MoonIcon , SunIcon } from 'lucide-react'
3+ import { motion , AnimatePresence } from 'framer-motion'
34
45import { browser } from 'wxt/browser'
56import { useRemeshDomain , useRemeshQuery , useRemeshSend } from 'remesh-react'
@@ -25,14 +26,12 @@ const AppButton: FC<AppButtonProps> = ({ children }) => {
2526
2627 const menuRef = useRef < HTMLDivElement > ( null )
2728
28- /**
29- * Waiting for PR merge
30- * @see https://github.com/streamich/react-use/pull/2528
31- */
3229 useClickAway ( menuRef , ( ) => {
3330 setOpen ( false )
3431 } , [ 'click' ] )
3532
33+ const handleToggleApp = ( ) => { }
34+
3635 const handleToggleMenu = ( e : MouseEvent < HTMLButtonElement > ) => {
3736 e . preventDefault ( )
3837 setOpen ( ! open )
@@ -52,35 +51,80 @@ const AppButton: FC<AppButtonProps> = ({ children }) => {
5251
5352 return (
5453 < div ref = { menuRef } className = "fixed bottom-5 right-5 z-infinity grid select-none justify-center gap-y-3" >
55- { /* <div className="grid gap-y-3" inert={!open && ''}> */ }
56- < div className = "pointer-events-none grid gap-y-3" >
57- < Button
58- onClick = { handleSwitchTheme }
59- variant = "outline"
60- data-state = { open ? 'open' : 'closed' }
61- className = "pointer-events-auto relative size-10 overflow-hidden rounded-full p-0 shadow fill-mode-forwards data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out data-[state=open]:fade-in data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom"
62- >
63- < div
64- className = { cn (
65- 'absolute -top-10 grid grid-rows-[repeat(2,minmax(0,2.5rem))] w-full justify-center items-center transition-all duration-500' ,
66- isDarkMode ? 'top-0' : '-top-10 ' ,
67- isDarkMode ? 'bg-slate-800 text-white' : 'bg-white text-orange-400'
68- ) }
54+ < AnimatePresence >
55+ { open && (
56+ < motion . div
57+ className = "grid gap-y-3"
58+ initial = "hidden"
59+ animate = "visible"
60+ exit = "exit"
61+ variants = { {
62+ hidden : { } ,
63+ visible : {
64+ transition : {
65+ staggerChildren : 0.1 ,
66+ staggerDirection : - 1
67+ }
68+ } ,
69+ exit : {
70+ transition : {
71+ staggerChildren : 0.1 ,
72+ staggerDirection : 1
73+ }
74+ }
75+ } }
6976 >
70- < MoonIcon size = { 20 } />
71- < SunIcon size = { 20 } />
72- </ div >
73- </ Button >
74- < Button
75- onClick = { handleOpenOptionsPage }
76- variant = "outline"
77- data-state = { open ? 'open' : 'closed' }
78- className = "pointer-events-auto size-10 rounded-full p-0 shadow fill-mode-forwards data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out data-[state=open]:fade-in data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom"
79- >
80- < SettingsIcon size = { 20 } />
81- </ Button >
82- </ div >
83- < Button onContextMenu = { handleToggleMenu } className = "relative z-10 size-10 rounded-full p-0 text-xs shadow" >
77+ < motion . div
78+ className = "leading-none"
79+ variants = { {
80+ hidden : { opacity : 0 , y : 12 } ,
81+ visible : { opacity : 1 , y : 0 } ,
82+ exit : { opacity : 0 , y : 12 }
83+ } }
84+ transition = { { duration : 0.1 } }
85+ >
86+ < Button
87+ onClick = { handleSwitchTheme }
88+ variant = "outline"
89+ className = "relative size-10 overflow-hidden rounded-full p-0 shadow"
90+ >
91+ < div
92+ className = { cn (
93+ 'absolute grid grid-rows-[repeat(2,minmax(0,2.5rem))] w-full justify-center items-center transition-all duration-500' ,
94+ isDarkMode ? 'top-0' : '-top-10' ,
95+ isDarkMode ? 'bg-slate-800 text-white' : 'bg-white text-orange-400'
96+ ) }
97+ >
98+ < MoonIcon size = { 20 } />
99+ < SunIcon size = { 20 } />
100+ </ div >
101+ </ Button >
102+ </ motion . div >
103+
104+ < motion . div
105+ variants = { {
106+ hidden : { opacity : 0 , y : 12 } ,
107+ visible : { opacity : 1 , y : 0 } ,
108+ exit : { opacity : 0 , y : 12 }
109+ } }
110+ transition = { { duration : 0.1 } }
111+ >
112+ < Button
113+ onClick = { handleOpenOptionsPage }
114+ variant = "outline"
115+ className = "pointer-events-auto size-10 rounded-full p-0 shadow"
116+ >
117+ < SettingsIcon size = { 20 } />
118+ </ Button >
119+ </ motion . div >
120+ </ motion . div >
121+ ) }
122+ </ AnimatePresence >
123+ < Button
124+ onClick = { handleToggleApp }
125+ onContextMenu = { handleToggleMenu }
126+ className = "relative z-10 size-10 rounded-full p-0 text-xs shadow"
127+ >
84128 { children }
85129 </ Button >
86130 </ div >
0 commit comments