@@ -22,10 +22,12 @@ import {
2222 alpha ,
2323 getThemeColor ,
2424 Container ,
25+ FloatingIndicator ,
26+ ButtonGroup ,
2527} from "@mantine/core" ;
2628import { useDisclosure } from "@mantine/hooks" ;
2729import { IconBrandReact , IconBrandVue , IconCode , IconPlayerPlay , IconRefresh } from "@tabler/icons-react" ;
28- import { startTransition , useEffect , useMemo , useState } from "react" ;
30+ import { startTransition , useCallback , useEffect , useMemo , useState } from "react" ;
2931
3032import { useDiffConfig } from "../hooks/useDiffConfig" ;
3133import { useDiffHighlighter } from "../hooks/useDiffHighlighter" ;
@@ -64,7 +66,7 @@ export const MainContent = () => {
6466
6567 const { colorScheme } = useMantineColorScheme ( ) ;
6668
67- const [ code , { toggle } ] = useDisclosure ( ) ;
69+ const [ code , { open , close } ] = useDisclosure ( ) ;
6870
6971 const [ platform , setPlatform ] = useState < "react" | "vue" > ( "react" ) ;
7072
@@ -94,6 +96,10 @@ export const MainContent = () => {
9496
9597 const { mode, highlight, engine, wrap } = useDiffConfig ( ) ;
9698
99+ const [ rootRef , setRootRef ] = useState < HTMLDivElement | null > ( null ) ;
100+
101+ const [ controlsRefs , setControlsRefs ] = useState < Record < string , HTMLButtonElement | null > > ( { } ) ;
102+
97103 return (
98104 < Container size = "xl" >
99105 < Flex mt = "lg" direction = { { base : "column" , sm : "row" } } >
@@ -120,11 +126,41 @@ export const MainContent = () => {
120126 w = { { base : "100%" , sm : "60%" } }
121127 >
122128 < Group className = "fixed right-6 top-2 z-10" >
123- < Tooltip label = { `show the ${ ! code ? "code" : "preview" } ` } >
124- < Button variant = "light" size = "compact-sm" onClick = { toggle } color = "grape" >
125- { ! code ? < IconCode className = "w-[1.2em]" /> : < IconPlayerPlay className = "w-[1.2em]" /> }
126- </ Button >
127- </ Tooltip >
129+ < div ref = { setRootRef } >
130+ < ButtonGroup >
131+ < Tooltip label = "show the code" >
132+ < Button
133+ variant = "light"
134+ size = "compact-sm"
135+ onClick = { open }
136+ color = "gray"
137+ ref = { useCallback ( ( node : HTMLButtonElement ) => setControlsRefs ( ( l ) => ( { ...l , code : node } ) ) , [ ] ) }
138+ >
139+ < IconCode className = "w-[1.2em]" />
140+ </ Button >
141+ </ Tooltip >
142+ < Tooltip label = "show the preview" >
143+ < Button
144+ variant = "light"
145+ size = "compact-sm"
146+ onClick = { close }
147+ color = "gray"
148+ ref = { useCallback (
149+ ( node : HTMLButtonElement ) => setControlsRefs ( ( l ) => ( { ...l , preview : node } ) ) ,
150+ [ ]
151+ ) }
152+ >
153+ < IconPlayerPlay className = "w-[1.2em]" />
154+ </ Button >
155+ </ Tooltip >
156+ </ ButtonGroup >
157+
158+ < FloatingIndicator
159+ target = { controlsRefs [ code ? "code" : "preview" ] }
160+ parent = { rootRef }
161+ className = "rounded-[var(--mantine-radius-default)] bg-[var(--mantine-color-violet-light)]"
162+ />
163+ </ div >
128164
129165 { ! code ? (
130166 < Tooltip label = "refresh" >
@@ -204,7 +240,7 @@ export const MainContent = () => {
204240 < Card key = { i } withBorder className = "relative" >
205241 < Text > { d } </ Text >
206242 < CloseButton
207- className = "absolute right-2 top-2 "
243+ className = "absolute right-1 top-1 "
208244 size = "xs"
209245 onClick = { ( ) => {
210246 setExtend ( ( prev ) => {
0 commit comments