Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Merge branch 'worktree-agent-ae1299e92e4462012' | 1 | import { type ComponentProps, type MouseEvent, type PointerEvent, type ReactElement, type ReactNode, useRef, useState } from "react"; |
| 2 | ||
| 3 | import { Tooltip, TooltipContent, TooltipTrigger } from "./tooltip"; | |
| 4 | ||
| 5 | /** | |
| 6 | * A hover hint: the site's tooltip around exactly one element, in place of | |
| 7 | * the browser's `title`, which g1t does not use (app/lib/no-native-title.test.ts | |
| 8 | * keeps it out). It opens on hover and keyboard focus, and on a tap of | |
| 9 | * something that does nothing else when tapped, since a touch screen has no | |
| 10 | * hover. Without a `label` the child renders as it is. | |
| 11 | * | |
| 12 | * The hint is not the element's accessible name: an icon-only button keeps | |
| 13 | * its `aria-label`, and text cut short keeps its whole text for a screen | |
| 14 | * reader. Anything else passed (as from a parent's `asChild`) goes to the child. | |
| 15 | */ | |
| 16 | export function Hint({ | |
| 17 | label, | |
| 18 | children, | |
| 19 | side, | |
| 20 | align, | |
| 21 | disabled, | |
| 22 | onClick, | |
| 23 | onPointerDown, | |
| 24 | ...props | |
| 25 | }: Omit<ComponentProps<typeof TooltipTrigger>, "children"> & { | |
| 26 | label: ReactNode; | |
| 27 | /** One element that takes a ref and passes its props on (asChild). */ | |
| 28 | children: ReactElement; | |
| 29 | side?: ComponentProps<typeof TooltipContent>["side"]; | |
| 30 | align?: ComponentProps<typeof TooltipContent>["align"]; | |
| 31 | /** | |
| 32 | * The child is disabled, so it gets no pointer events and no focus: the | |
| 33 | * hint hangs on a focusable span around it instead, as when it says why. | |
| 34 | */ | |
| 35 | disabled?: boolean; | |
| 36 | }) { | |
| 37 | const [open, setOpen] = useState(false); | |
| 38 | const touch = useRef(false); | |
| 39 | if (label == null || label === false || label === "") return children; | |
| 40 | const trigger = disabled ? ( | |
| 41 | <span tabIndex={0} className="inline-flex rounded-md outline-none focus-visible:ring-2 focus-visible:ring-accent *:pointer-events-none"> | |
| 42 | {children} | |
| 43 | </span> | |
| 44 | ) : ( | |
| 45 | children | |
| 46 | ); | |
| 47 | return ( | |
| 48 | <Tooltip open={open} onOpenChange={setOpen}> | |
| 49 | <TooltipTrigger | |
| 50 | asChild | |
| 51 | {...props} | |
| 52 | onPointerDown={(event: PointerEvent<HTMLButtonElement>) => { | |
| 53 | touch.current = event.pointerType === "touch"; | |
| 54 | onPointerDown?.(event); | |
| 55 | }} | |
| 56 | onClick={(event: MouseEvent<HTMLButtonElement>) => { | |
| 57 | onClick?.(event); | |
| 58 | // A tap on text or a badge shows the hint; a tap on a link or a | |
| 59 | // button does what it does. preventDefault keeps the trigger's own | |
| 60 | // click handler from closing the hint again. | |
| 61 | if (touch.current && !event.defaultPrevented && !(event.target as Element).closest("a, button, input, select, textarea, label, summary")) { | |
| 62 | event.preventDefault(); | |
| 63 | setOpen(true); | |
| 64 | } | |
| 65 | }} | |
| 66 | > | |
| 67 | {trigger} | |
| 68 | </TooltipTrigger> | |
| 69 | <TooltipContent side={side} align={align}> | |
| 70 | {label} | |
| 71 | </TooltipContent> | |
| 72 | </Tooltip> | |
| 73 | ); | |
| 74 | } |
This file's history is long; its oldest lines are credited to the oldest commit read.