UI

Popover

Displays rich content in a portal, triggered by a button.

Installation

  1. 1

    Install dependencies:

    npm install @radix-ui/react-popover
  2. 2

    Add component:

    Copy and paste the code into your project’s component directory. Do not forget to update the import paths.
    // Tremor Popover [v0.0.3]
    import React from "react"import * as PopoverPrimitives from "@radix-ui/react-popover"
    import { cx } from "@/lib/utils"
    const Popover = (  props: React.ComponentPropsWithoutRef<typeof PopoverPrimitives.Root>,) => {  return <PopoverPrimitives.Root {...props} />}
    Popover.displayName = "Popover"
    const PopoverTrigger = React.forwardRef<  React.ElementRef<typeof PopoverPrimitives.Trigger>,  React.ComponentPropsWithoutRef<typeof PopoverPrimitives.Trigger>>((props, forwardedRef) => {  return <PopoverPrimitives.Trigger ref={forwardedRef} {...props} />})
    PopoverTrigger.displayName = "PopoverTrigger"
    const PopoverAnchor = React.forwardRef<  React.ElementRef<typeof PopoverPrimitives.Anchor>,  React.ComponentPropsWithoutRef<typeof PopoverPrimitives.Anchor>>((props, forwardedRef) => {  return <PopoverPrimitives.Anchor ref={forwardedRef} {...props} />})
    PopoverAnchor.displayName = "PopoverAnchor"
    const PopoverClose = React.forwardRef<  React.ElementRef<typeof PopoverPrimitives.Close>,  React.ComponentPropsWithoutRef<typeof PopoverPrimitives.Close>>((props, forwardedRef) => {  return <PopoverPrimitives.Close ref={forwardedRef} {...props} />})
    PopoverClose.displayName = "PopoverClose"
    type ContentProps = React.ComponentPropsWithoutRef<  typeof PopoverPrimitives.Content>
    const PopoverContent = React.forwardRef<  React.ElementRef<typeof PopoverPrimitives.Content>,  ContentProps>(  (    {      className,      sideOffset = 10,      side = "bottom",      align = "center",      collisionPadding,      avoidCollisions = true,      ...props    }: ContentProps,    forwardedRef,  ) => {    return (      <PopoverPrimitives.Portal>        <PopoverPrimitives.Content          ref={forwardedRef}          sideOffset={sideOffset}          side={side}          align={align}          collisionPadding={collisionPadding}          avoidCollisions={avoidCollisions}          className={cx(            // base            "max-h-[var(--radix-popper-available-height)] min-w-60 overflow-hidden rounded-md border p-2.5 text-sm shadow-md",            // border color            "border-gray-200 dark:border-gray-800",            // text color            "text-gray-900 dark:text-gray-50",            // background color            "bg-white dark:bg-gray-950",            // transition            "will-change-[transform,opacity]",            "data-[state=closed]:animate-hide",            "data-[state=open]:data-[side=bottom]:animate-slideDownAndFade data-[state=open]:data-[side=left]:animate-slideLeftAndFade data-[state=open]:data-[side=right]:animate-slideRightAndFade data-[state=open]:data-[side=top]:animate-slideUpAndFade",
                className,          )}          tremor-id="tremor-raw"          // https://github.com/radix-ui/primitives/issues/1159          onWheel={(event) => {            event.stopPropagation()            const isScrollingDown = event.deltaY > 0            if (isScrollingDown) {              event.currentTarget.dispatchEvent(                new KeyboardEvent("keydown", { key: "ArrowDown" }),              )            } else {              event.currentTarget.dispatchEvent(                new KeyboardEvent("keydown", { key: "ArrowUp" }),              )            }          }}          {...props}        />      </PopoverPrimitives.Portal>    )  },)PopoverContent.displayName = "PopoverContent"
    export { Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger }
    
  3. 3

    Update tailwind.config.ts

    import type { Config } from 'tailwindcss';export default {  // ...  theme: {    extend: {      keyframes: {        hide: {          from: { opacity: "1" },          to: { opacity: "0" },        },        slideDownAndFade: {          from: { opacity: "0", transform: "translateY(-6px)" },          to: { opacity: "1", transform: "translateY(0)" },        },        slideLeftAndFade: {          from: { opacity: "0", transform: "translateX(6px)" },          to: { opacity: "1", transform: "translateX(0)" },        },        slideUpAndFade: {          from: { opacity: "0", transform: "translateY(6px)" },          to: { opacity: "1", transform: "translateY(0)" },        },        slideRightAndFade: {          from: { opacity: "0", transform: "translateX(-6px)" },          to: { opacity: "1", transform: "translateX(0)" },        },      },      animation: {        hide: "hide 150ms cubic-bezier(0.16, 1, 0.3, 1)",        slideDownAndFade:          "slideDownAndFade 150ms cubic-bezier(0.16, 1, 0.3, 1)",        slideLeftAndFade:          "slideLeftAndFade 150ms cubic-bezier(0.16, 1, 0.3, 1)",        slideUpAndFade: "slideUpAndFade 150ms cubic-bezier(0.16, 1, 0.3, 1)",        slideRightAndFade:          "slideRightAndFade 150ms cubic-bezier(0.16, 1, 0.3, 1)",      },    },  },  // ...} satisfies Config;

Example

API Reference: Popover

This component uses the Radix UI API.

API Reference: PopoverAnchor

This component uses the Radix UI API.

API Reference: PopoverClose

This component uses the Radix UI API.

API Reference: PopoverContent

This component uses the Radix UI API.

align
"center" | "start" | "end"
Preferred alignment against the anchor.

Default: "center"

side
"bottom" | "left" | "top" | "right"
Placement of the tooltip relative to the trigger.

Default: "bottom"

sideOffset
number
Distance from anchor.

Default: 10

API Reference: PopoverTrigger

This component uses the Radix UI API.