Tipover
jarvis-ui/tipoverFreeComponent
A touch-friendly tooltip/popover hybrid.
Live preview
live · rendered by the registry
Rendered by jarvis-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://ui.jarv.is/r/tipover.jsonSource
1"use client";23import { Popover as PopoverPrimitive } from "@base-ui/react/popover";4import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip";5import * as React from "react";67import { cn } from "@/lib/utils";89import { usePointerCapability } from "@/hooks/use-pointer-capability";1011type TipoverContextValue = {12 isTouchDevice: boolean;13};1415const TipoverContext = React.createContext<TipoverContextValue | null>(null);1617function Tipover({ ...props }: PopoverPrimitive.Root.Props & TooltipPrimitive.Root.Props) {18 const { isTouchDevice } = usePointerCapability();19 const contextValue = React.useMemo(() => ({ isTouchDevice }), [isTouchDevice]);2021 return (22 <TipoverContext.Provider value={contextValue}>23 {isTouchDevice ? (24 <PopoverPrimitive.Root data-slot="tipover" {...props} />25 ) : (26 <TooltipPrimitive.Provider delay={0}>27 <TooltipPrimitive.Root data-slot="tipover" {...props} />28 </TooltipPrimitive.Provider>29 )}30 </TipoverContext.Provider>31 );32}3334function TipoverTrigger({35 nativeButton,36 closeDelay,37 ...props38}: Omit<TooltipPrimitive.Trigger.Props & PopoverPrimitive.Trigger.Props, "handle"> &39 Pick<PopoverPrimitive.Trigger.Props, "nativeButton">) {40 const ctx = useTipoverContext("TipoverTrigger");41 const { Trigger } = ctx.isTouchDevice ? PopoverPrimitive : TooltipPrimitive;42 const triggerProps = ctx.isTouchDevice43 ? ({44 nativeButton,45 openOnHover: true,46 } satisfies PopoverPrimitive.Trigger.Props)47 : ({48 closeDelay: closeDelay ?? 150,49 } satisfies TooltipPrimitive.Trigger.Props);5051 return <Trigger data-slot="tipover-trigger" {...props} {...triggerProps} />;52}5354function TipoverContent({55 className,56 side = "top",57 sideOffset = 4,58 align = "center",59 alignOffset = 0,60 children,61 ...props62}: TooltipPrimitive.Popup.Props &63 PopoverPrimitive.Popup.Props &64 Pick<TooltipPrimitive.Positioner.Props, "align" | "alignOffset" | "side" | "sideOffset">) {65 const ctx = useTipoverContext("TipoverContent");66 const { Portal, Positioner, Popup, Arrow } = ctx.isTouchDevice67 ? PopoverPrimitive68 : TooltipPrimitive;6970 return (71 <Portal>72 <Positioner73 align={align}74 alignOffset={alignOffset}75 side={side}76 sideOffset={sideOffset}77 className="pointer-events-auto isolate z-50"78 >79 <Popup80 data-slot="tipover-content"81 className={cn(82// … truncated
What it pulls in
npm packages
Files it writes
More from jarvis-ui
All 10 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Browser Windowbrowser-window | jarvis-ui | Components | Free | no deps | |
| Cookie Consentcookie-consent | jarvis-ui | Components | Free | no deps | |
| Copy Buttoncopy-button | jarvis-ui | Components | Free | 1 dep | |
| Copyable Fieldcopyable-field | jarvis-ui | Components | Free | no deps | |
| Parallax Cardparallax-card | jarvis-ui | Components | Free | 1 dep | |
| Scroll Areascroll-area | jarvis-ui | Components | Free | 1 dep | |
| Stepperstepper | jarvis-ui | Components | Free | 1 dep | |
| Toasttoast | jarvis-ui | Components | Free | 2 deps |
