From 16752a7ae85002ace699e3d96884c3220b35edc7 Mon Sep 17 00:00:00 2001 From: Yiyang Suen Date: Tue, 9 Dec 2025 09:22:30 +0800 Subject: [PATCH 1/2] feat: add content-clamp component to show clamped text --- src/components/launch/LaunchWindow.tsx | 10 +-- src/components/ui/content-clamp.tsx | 86 ++++++++++++++++++++++++++ src/components/ui/popover.tsx | 24 ++++++- 3 files changed, 110 insertions(+), 10 deletions(-) create mode 100644 src/components/ui/content-clamp.tsx 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..9113084 --- /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 } From 4bc8a1e970479039aa6e92698beeaec60f374351 Mon Sep 17 00:00:00 2001 From: Yiyang Suen Date: Tue, 9 Dec 2025 09:31:35 +0800 Subject: [PATCH 2/2] feat: remove content clamp popover content box shadow --- src/components/ui/content-clamp.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ui/content-clamp.tsx b/src/components/ui/content-clamp.tsx index 9113084..1597f1b 100644 --- a/src/components/ui/content-clamp.tsx +++ b/src/components/ui/content-clamp.tsx @@ -68,7 +68,7 @@ function ContentClamp({