a programming education platform
www.hypercommit.com
education
1"use client"
2
3import { Copy01Icon, FileCodeIcon, Tick02Icon } from "@hugeicons/core-free-icons"
4import { HugeiconsIcon } from "@hugeicons/react"
5import { Tooltip } from "@base-ui/react/tooltip"
6import { cn } from "@workspace/ui/lib/utils"
7import { Button } from "@workspace/ui/components/button"
8import { useCopyToClipboard } from "./use-copy-to-clipboard"
9
10export function CopyCodeButton({
11 getCode,
12 className,
13}: {
14 getCode: () => string
15 className?: string
16}) {
17 const { copyToClipboard, isCopied } = useCopyToClipboard()
18
19 return (
20 <Tooltip.Provider delay={100} closeDelay={50}>
21 <Tooltip.Root>
22 <Tooltip.Trigger
23 render={
24 <Button
25 className={cn("size-7 shrink-0", className)}
26 onClick={() => copyToClipboard(getCode())}
27 size="icon"
28 variant="ghost"
29 aria-label="Copy to clipboard"
30 >
31 <HugeiconsIcon
32 icon={isCopied ? Tick02Icon : Copy01Icon}
33 className="size-3.5"
34 />
35 </Button>
36 }
37 />
38 <Tooltip.Portal>
39 <Tooltip.Positioner side="bottom" sideOffset={6}>
40 <Tooltip.Popup
41 className={cn(
42 "rounded-md border bg-popover px-2 py-1 text-xs text-popover-foreground shadow-md",
43 "origin-[var(--transform-origin)]",
44 "data-[open]:animate-in data-[open]:fade-in-0 data-[open]:zoom-in-95",
45 "data-[closed]:animate-out data-[closed]:fade-out-0 data-[closed]:zoom-out-95",
46 "data-[side=bottom]:slide-in-from-top-1",
47 "data-[side=top]:slide-in-from-bottom-1",
48 "data-[side=left]:slide-in-from-right-1",
49 "data-[side=right]:slide-in-from-left-1",
50 "data-[instant]:animate-none"
51 )}
52 >
53 {isCopied ? "Copied" : "Copy to clipboard"}
54 </Tooltip.Popup>
55 </Tooltip.Positioner>
56 </Tooltip.Portal>
57 </Tooltip.Root>
58 </Tooltip.Provider>
59 )
60}
61
62export function CodeBlockHeader({
63 filename,
64 getCode,
65}: {
66 filename: string
67 getCode: () => string
68}) {
69 return (
70 <div className="flex items-center justify-between gap-2 py-1 ps-3 pe-1">
71 <span className="flex min-w-0 items-center gap-1.5 font-mono text-xs text-muted-foreground">
72 <HugeiconsIcon icon={FileCodeIcon} className="size-3.5 shrink-0" />
73 <span className="truncate">{filename}</span>
74 </span>
75 <CopyCodeButton getCode={getCode} />
76 </div>
77 )
78}