diff --git a/src/components/launch/LaunchWindow.tsx b/src/components/launch/LaunchWindow.tsx index 963e07f..f82ae6c 100644 --- a/src/components/launch/LaunchWindow.tsx +++ b/src/components/launch/LaunchWindow.tsx @@ -8,6 +8,7 @@ import { MdMonitor } from "react-icons/md"; import { RxDragHandleDots2 } from "react-icons/rx"; import { FaFolderMinus } from "react-icons/fa6"; import { FiMinus, FiX } from "react-icons/fi"; +import { ContentClamp } from "../ui/content-clamp"; export function LaunchWindow() { const { recording, toggleRecording } = useScreenRecorder(); @@ -61,11 +62,6 @@ export function LaunchWindow() { return () => clearInterval(interval); }, []); - const truncateText = (text: string, maxLength: number = 6) => { - if (text.length <= maxLength) return text; - return text.substring(0, maxLength) + "..."; - }; - const openSourceSelector = () => { if (window.electronAPI) { window.electronAPI.openSourceSelector(); @@ -121,7 +117,7 @@ export function LaunchWindow() { disabled={recording} > - {truncateText(selectedSource, 6)} + {selectedSource}
@@ -131,7 +127,7 @@ export function LaunchWindow() { size="sm" onClick={hasSelectedSource ? toggleRecording : openSourceSelector} disabled={!hasSelectedSource && !recording} - className={`gap-1 bg-transparent hover:bg-transparent px-0 flex-1 text-center text-xs ${styles.electronNoDrag}`} + className={`gap-1 text-white bg-transparent hover:bg-transparent px-0 flex-1 text-center text-xs ${styles.electronNoDrag}`} > {recording ? ( <> diff --git a/src/components/ui/content-clamp.tsx b/src/components/ui/content-clamp.tsx new file mode 100644 index 0000000..1597f1b --- /dev/null +++ b/src/components/ui/content-clamp.tsx @@ -0,0 +1,86 @@ +"use client" + +import * as React from "react" + +import { cn } from "@/lib/utils" +import { Popover, PopoverArrow, PopoverContent, PopoverTrigger } from "./popover" + +interface ContentClampProps extends React.HTMLAttributes { + children: React.ReactNode + truncateLength?: number +} + +function ContentClamp({ + children, + className, + truncateLength = 50, + ...props +}: ContentClampProps) { + const text = typeof children === "string" ? children : String(children ?? "") + const isTruncated = text.length > truncateLength + + const [open, setOpen] = React.useState(false) + const timeoutRef = React.useRef(null) + + const handleMouseEnter = () => { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current) + timeoutRef.current = null + } + setOpen(true) + } + + const handleMouseLeave = () => { + timeoutRef.current = setTimeout(() => { + setOpen(false) + }, 100) + } + + React.useEffect(() => { + return () => { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current) + } + } + }, []) + + if (!isTruncated) { + return ( +
+ {children} +
+ ) + } + + const truncatedText = text.slice(0, truncateLength) + "..." + + return ( + + + e.preventDefault()} + {...props} + > + {truncatedText} + + + e.preventDefault()} + onClick={(e) => e.stopPropagation()} + > + + {children} + + + ) +} + +export { ContentClamp } diff --git a/src/components/ui/popover.tsx b/src/components/ui/popover.tsx index 01e468b..2f36cd6 100644 --- a/src/components/ui/popover.tsx +++ b/src/components/ui/popover.tsx @@ -21,8 +21,11 @@ function PopoverContent({ className, align = "center", sideOffset = 4, + animated = true, ...props -}: React.ComponentProps) { +}: React.ComponentProps & { + animated?: boolean +}) { return ( } -export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor } +function PopoverArrow({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor, PopoverArrow }