Popover

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

import { Info, X } from "lucide-react";
import Popover from "@tailus-ui/Popover";
import Button from "@tailus-ui/Button";
import { Text, Title } from "@tailus-ui/typography";

export const Overview = () => (
    <Popover.Root>
      <Popover.Trigger asChild>
        <Button.Root variant="ghost" intent="gray">
          <Button.Icon type="only">
            <Info />
          </Button.Icon>
        </Button.Root>
      </Popover.Trigger>
      <Popover.Portal>
        <Popover.Content mixed className="max-w-xs">
          <Title size="base" as="div" weight="medium">Popover Title</Title>
          <Text className="mt-2 mb-0">This is a description for the popover.</Text>
          <Popover.Close asChild>
            <Button.Root variant="outlined" size="sm" intent="gray">
              <Button.Icon type="only">
                <X />
              </Button.Icon>
            </Button.Root>
          </Popover.Close>
      </Popover.Content>
      </Popover.Portal>
    </Popover.Root>
)

Installation

Install the primitive and Copy-Paste the component code in a .tsx file.

npm install @radix-ui/react-popover
import * as Popover from "@radix-ui/react-popover";
import React from "react";
import { popover, type PopoverProps } from "@tailus/themer";

const PopoverRoot = Popover.Root;
const PopoverTrigger = Popover.Trigger;
const PopoverAnchor = Popover.Anchor;
const PopoverPortal = Popover.Portal;

const PopoverContent = React.forwardRef<
  React.ElementRef<typeof Popover.Content>,
  React.ComponentPropsWithoutRef<typeof Popover.Content> & PopoverProps
  >(({ className, fancy, mixed, ...props }, forwardedRef) => {

    const { content } = popover()

    if (fancy && mixed) {
      throw new Error('The fancy and mixed props cannot be used together.');
    }

    return(
      <Popover.Content
        {...props}
        ref={forwardedRef}
        className={content({ fancy, mixed, className })}
      />
    )
});

const PopoverClose = React.forwardRef<
  React.ElementRef<typeof Popover.Close>,
  React.ComponentPropsWithoutRef<typeof Popover.Close>
  >(({ className, ...props }, forwardedRef) => {

    const { close } = popover()

    return(
      <Popover.Close
        {...props}
        ref={forwardedRef}
        className={close({ className })}
      />
    )
  });

const PopoverArrow = React.forwardRef<
  React.ElementRef<typeof Popover.Arrow>,
  React.ComponentPropsWithoutRef<typeof Popover.Arrow>
  >(({ className, ...props }, forwardedRef) => {
    const { arrow } = popover()
    return(
      <Popover.Arrow
        {...props}
        ref={forwardedRef}
        className={arrow({ className })}
      />
    )
  });

export {
  PopoverRoot,
  PopoverTrigger,
  PopoverAnchor,
  PopoverPortal,
  PopoverContent,
  PopoverClose,
  PopoverArrow
};

export default {
  Root: PopoverRoot,
  Trigger: PopoverTrigger,
  Anchor: PopoverAnchor,
  Portal: PopoverPortal,
  Content: PopoverContent,
  Close: PopoverClose,
  Arrow: PopoverArrow
}

Usage

Import all the parts and build your Dialog.

import { Info, X } from "lucide-react";
import Popover from "@tailus-ui/Popover";
import Button from "@tailus-ui/Button";
import { Text, Title } from "@tailus-ui/typography";

export const Overview = () => (
    <Popover.Root>
      <Popover.Trigger asChild>
        <Button.Root variant="ghost" intent="gray">
          <Button.Icon type="only">
            <Info />
          </Button.Icon>
        </Button.Root>
      </Popover.Trigger>
      <Popover.Portal>
        <Popover.Content mixed className="max-w-xs">
          <Title size="base" as="div" weight="medium">Popover Title</Title>
          <Text className="mt-2 mb-0">This is a description for the popover.</Text>
          <Popover.Close asChild>
            <Button.Root variant="outlined" size="sm" intent="gray">
              <Button.Icon type="only">
                <X />
              </Button.Icon>
            </Button.Root>
          </Popover.Close>
      </Popover.Content>
      </Popover.Portal>
    </Popover.Root>
)

Reference

Content

The content of the Popover component

Prop
Type
Default
mixed
boolean
-
fancy
boolean
-

Examples