- Accordion
- Agent Thinking
- Alert
- Alert Dialog
- Announcement
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Calendar
- Card
- Carousel
- Checkbox
- Checkbox Card
- Code Block
- Collapsible
- Color Picker
- Combobox
- Command
- Composer
- Composer Loader
- Context Menu
- Data Grid
- Data Table
- Date Picker
- Dialog
- Direction
- Drawer
- Dropdown Menu
- Empty
- Field
- File Upload
- Hover Card
- Input
- Input Group
- Input Otp
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Message Scroller
- Meter
- Native Select
- Navigation Menu
- Number Field
- Pagination
- Period Switcher
- Popover
- Progress
- Questionnaire
- Radio Card
- Radio Group
- Resizable
- Reveal
- Scroll Area
- Search Field
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Social Button
- Sonner
- Spinner
- Status Dot
- Switch
- Switch Card
- Table
- Tabs
- Tag Group
- Textarea
- Theme Toggle
- Time Field
- Toggle
- Toggle Group
- Tooltip
- Trace
- Tree View
- Agent Creator 01
- Agent Limits Card 01
- Agent Progress 01
- AI Chat 01
- AI Image Generation 01
- AI Profile 01
- Alerts Card 01
- Auth Card 01
- Calendar 01
- Composer 01
- Composer Attachments 01
- Composer Panel 01
- Finance Dashboard 01
- Home Dashboard 01
- Marketing Dashboard 01
- Medical Profile 01
- Meeting Scheduler 01
- Multi Agent Chat 01
- Notification Center 01
- Patient Info Card 01
- Project Board 01
- Questionnaire 01
- Settings Modal 01
- Sidebar 01
- Stat Cards 01
- Task List 01
- Web Search 01
- Activity Rings Card 01
- Area Chart Card 01
- Bar List Card 01
- Combo Chart Card 01
- Contributions Card 01
- Earnings Chart Card 01
- Funnel Chart Card 01
- Heatmap Chart Card 01
- Line Chart Card 01
- Most Active Days Card 01
- Orders Chart Card 01
- Radar Chart Card 01
- Radial Chart Card 01
- Revenue Chart Card 01
- Sankey Chart Card 01
- Scatter Chart Card 01
- Sleep Score Card 01
- Stage Bars Card 01
- Steps Card 01
Net revenue retention
Installation
$ pnpm dlx shadcn@latest add @cobalt/popover
Options
<PopoverContent size="flush">removes padding and gap, for lists, calendars and other content that draws its own edges.size="sm"is a compact panel (12px padding, 8px gap).size="xs"is a menu-like list (6px padding, 2px gap).radiussets the corner radius in px (12,16,20,24). The default is20.variant="ghost"draws no border, fill, shadow or ring, for aCardplaced inside so only one frame shows.
Source
"use client";
import { Popover as PopoverPrimitive } from "@base-ui/react/popover";
import { cn } from "cn";
import * as React from "react";
const POPOVER_RADIUS = {
12: "rounded-[12px]",
16: "rounded-[16px]",
20: "rounded-[20px]",
24: "rounded-[24px]",
} as const;
function Popover({ ...props }: PopoverPrimitive.Root.Props) {
return <PopoverPrimitive.Root data-slot="popover" {...props} />;
}
function PopoverTrigger({ ...props }: PopoverPrimitive.Trigger.Props) {
return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />;
}
function PopoverContent({
className,
align = "center",
alignOffset = 0,
side = "bottom",
sideOffset,
collisionAvoidance,
collisionPadding = 8,
positionMethod,
showArrow = false,
size = "default",
radius = 20,
variant = "default",
...props
}: PopoverPrimitive.Popup.Props &
Pick<
PopoverPrimitive.Positioner.Props,
| "align"
| "alignOffset"
| "side"
| "sideOffset"
| "collisionAvoidance"
| "collisionPadding"
| "positionMethod"
> & {
showArrow?: boolean;
/**
* `sm` is a compact panel (12px padding). `xs` is a menu-like list
* (6px padding). `flush` has no padding.
*/
size?: "default" | "sm" | "xs" | "flush";
/** Corner radius in px. */
radius?: 12 | 16 | 20 | 24;
/** `ghost` has no border, fill, shadow or ring, for a Card placed inside. */
variant?: "default" | "ghost";
}) {
return (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Positioner
align={align}
alignOffset={alignOffset}
side={side}
sideOffset={sideOffset ?? (showArrow ? 10 : 8)}
collisionAvoidance={collisionAvoidance}
collisionPadding={collisionPadding}
positionMethod={positionMethod}
className="isolate z-50"
>
<PopoverPrimitive.Popup
data-slot="popover-content"
data-size={size}
className={cn(
"flex max-h-[var(--available-height)] w-80 max-w-[calc(100vw-32px)] origin-(--transform-origin) flex-col gap-3 rounded-[20px] border border-[var(--border-subtle,var(--border))] bg-popover p-4 text-sm text-popover-foreground shadow-[shadow:var(--shadow-dropdown,0_1px_1px_0_rgb(0_0_0/0.04),0_4px_4px_0_rgb(0_0_0/0.02))] outline-none transition-[opacity,scale,filter] duration-150 ease-out data-starting-style:opacity-0 data-ending-style:opacity-0 motion-safe:data-starting-style:scale-95 motion-safe:data-starting-style:blur-[2px] motion-safe:data-ending-style:scale-95 motion-safe:data-ending-style:blur-[2px] motion-reduce:transition-opacity",
POPOVER_RADIUS[radius],
size === "sm" && "gap-2 p-3",
size === "xs" && "gap-0.5 p-1.5",
size === "flush" && "gap-0 p-0",
variant === "ghost" &&
"border-0 bg-transparent p-0 shadow-none ring-0",
className
)}
{...props}
>
{showArrow && (
<PopoverPrimitive.Arrow className="data-[side=bottom]:-top-[6px] data-[side=top]:-bottom-[6px] data-[side=left]:-right-[6px] data-[side=right]:-left-[6px]">
<svg
aria-hidden="true"
width="12"
height="7"
viewBox="0 0 12 7"
className="hidden overflow-visible fill-popover stroke-[var(--border-subtle,var(--border))] [filter:drop-shadow(0_-1.5px_1px_rgb(0_0_0/0.05))] in-data-[side=bottom]:block"
>
<path d="M0 7 L6 1 L12 7" />
</svg>
<svg
aria-hidden="true"
width="12"
height="7"
viewBox="0 0 12 7"
className="hidden overflow-visible fill-popover stroke-[var(--border-subtle,var(--border))] [filter:drop-shadow(0_1.5px_1px_rgb(0_0_0/0.05))] in-data-[side=top]:block"
>
<path d="M0 0 L6 6 L12 0" />
</svg>
<svg
aria-hidden="true"
width="7"
height="12"
viewBox="0 0 7 12"
className="hidden overflow-visible fill-popover stroke-[var(--border-subtle,var(--border))] [filter:drop-shadow(0_1.5px_1px_rgb(0_0_0/0.05))] in-data-[side=left]:block"
>
<path d="M0 0 L6 6 L0 12" />
</svg>
<svg
aria-hidden="true"
width="7"
height="12"
viewBox="0 0 7 12"
className="hidden overflow-visible fill-popover stroke-[var(--border-subtle,var(--border))] [filter:drop-shadow(0_1.5px_1px_rgb(0_0_0/0.05))] in-data-[side=right]:block"
>
<path d="M7 0 L1 6 L7 12" />
</svg>
</PopoverPrimitive.Arrow>
)}
{props.children}
</PopoverPrimitive.Popup>
</PopoverPrimitive.Positioner>
</PopoverPrimitive.Portal>
);
}
function PopoverHeader({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="popover-header"
className={cn("flex flex-col gap-0.5 text-sm", className)}
{...props}
/>
);
}
function PopoverFooter({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="popover-footer"
className={cn("flex items-center justify-end gap-2", className)}
{...props}
/>
);
}
function PopoverTitle({ className, ...props }: PopoverPrimitive.Title.Props) {
return (
<PopoverPrimitive.Title
data-slot="popover-title"
className={cn("font-medium", className)}
{...props}
/>
);
}
function PopoverDescription({
className,
...props
}: PopoverPrimitive.Description.Props) {
return (
<PopoverPrimitive.Description
data-slot="popover-description"
className={cn("text-muted-foreground", className)}
{...props}
/>
);
}
export {
Popover,
PopoverContent,
PopoverDescription,
PopoverHeader,
PopoverFooter,
PopoverTitle,
PopoverTrigger,
}; On this page