From b48fdcc2d5241d134e924b8f6dfed9aac85af575 Mon Sep 17 00:00:00 2001 From: Stephen Jennings Date: Mon, 13 Jul 2026 16:52:38 -0700 Subject: [PATCH] feat(home): make PR list items middle-clickable via BlockLink Home-page PR rows were rendered as + ); } diff --git a/src/browser/ui/block-link.tsx b/src/browser/ui/block-link.tsx new file mode 100644 index 0000000..b60963d --- /dev/null +++ b/src/browser/ui/block-link.tsx @@ -0,0 +1,80 @@ +import * as React from "react"; +import { Slot as SlotPrimitive } from "radix-ui"; + +// A ref that BlockLink.Root uses to know where its BlockLink.Link is. Root +// clicks are re-dispatched onto this element so the browser handles them as +// native activation. +type BlockLinkContextValue = { + linkRef: React.RefObject; +}; + +const BlockLinkContext = React.createContext( + null +); + +type RootProps = Omit, "onClick"> & { + onClick?: React.MouseEventHandler; + children: React.ReactNode; + asChild?: boolean; +}; + +function Root({ onClick, children, asChild, ...props }: RootProps) { + const linkRef = React.useRef(null); + + const handleClick = React.useCallback( + (e: React.MouseEvent) => { + onClick?.(e); + if (e.defaultPrevented) return; + const link = linkRef.current; + if (link && !link.contains(e.target as Node)) { + link.click(); + } + }, + [onClick] + ); + + const Comp = asChild ? SlotPrimitive.Slot : "div"; + + return ( + + + {children} + + + ); +} + +type LinkOwnProps = { + asChild?: boolean; + children: React.ReactNode; +}; + +type LinkProps = LinkOwnProps & + Omit, keyof LinkOwnProps>; + +function Link({ asChild, children, onClick, ...props }: LinkProps) { + const context = React.useContext(BlockLinkContext); + const localRef = React.useRef(null); + + const setRef = React.useCallback( + (el: HTMLElement | null) => { + localRef.current = el; + if (context) context.linkRef.current = el; + }, + [context] + ); + + const handleClick = (e: React.MouseEvent) => { + e.stopPropagation(); + onClick?.(e as React.MouseEvent); + }; + + const Comp = asChild ? SlotPrimitive.Slot : "a"; + return ( + + {children} + + ); +} + +export const BlockLink = { Root, Link };