Docs
Popover
Popover
Displays rich content in a portal, triggered by a button.
import type { PopoverTriggerProps } from "@kobalte/core/popover";
import { Button } from "@repo/tailwindcss/ui/button";
import {
Popover,
PopoverContent,
PopoverDescription,
PopoverTitle,
PopoverTrigger,
} from "@repo/tailwindcss/ui/popover";
import {
TextField,
TextFieldLabel,
TextFieldRoot,
} from "@repo/tailwindcss/ui/textfield";
const PopoverDemo = () => {
return (
<Popover>
<PopoverTrigger
as={(props: PopoverTriggerProps) => (
<Button variant="outline" {...props}>
Open popover
</Button>
)}
/>
<PopoverContent class="w-80">
<div class="grid gap-4">
<PopoverTitle class="space-y-2">
<h4 class="font-medium leading-none">Dimensions</h4>
<p class="text-sm text-muted-foreground">
Set the dimensions for the layer.
</p>
</PopoverTitle>
<PopoverDescription class="grid gap-2">
<TextFieldRoot class="grid grid-cols-3 items-center gap-4">
<TextFieldLabel class="text-right">Width</TextFieldLabel>
<TextField value="100%" class="col-span-2 h-8" />
</TextFieldRoot>
<TextFieldRoot class="grid grid-cols-3 items-center gap-4">
<TextFieldLabel class="text-right">Max. width</TextFieldLabel>
<TextField value="300px" class="col-span-2 h-8" />
</TextFieldRoot>
<TextFieldRoot class="grid grid-cols-3 items-center gap-4">
<TextFieldLabel class="text-right">Height</TextFieldLabel>
<TextField value="25px" class="col-span-2 h-8" />
</TextFieldRoot>
<TextFieldRoot class="grid grid-cols-3 items-center gap-4">
<TextFieldLabel class="text-right">Max. height</TextFieldLabel>
<TextField value="none" class="col-span-2 h-8" />
</TextFieldRoot>
</PopoverDescription>
</div>
</PopoverContent>
</Popover>
);
};
export default PopoverDemo;
Installation
npx shadcn-solid@latest add popover
Install the following dependencies:
npm install @kobalte/core
Copy and paste the following code into your project:
import { cn } from "@/libs/cn";
import type { PolymorphicProps } from "@kobalte/core/polymorphic";
import type {
PopoverContentProps,
PopoverRootProps,
} from "@kobalte/core/popover";
import { Popover as PopoverPrimitive } from "@kobalte/core/popover";
import type { ParentProps, ValidComponent } from "solid-js";
import { mergeProps, splitProps } from "solid-js";
export const PopoverTrigger = PopoverPrimitive.Trigger;
export const PopoverTitle = PopoverPrimitive.Title;
export const PopoverDescription = PopoverPrimitive.Description;
export const Popover = (props: PopoverRootProps) => {
const merge = mergeProps<PopoverRootProps[]>(
{
gutter: 4,
flip: false,
},
props,
);
return <PopoverPrimitive {...merge} />;
};
type popoverContentProps<T extends ValidComponent = "div"> = ParentProps<
PopoverContentProps<T> & {
class?: string;
}
>;
export const PopoverContent = <T extends ValidComponent = "div">(
props: PolymorphicProps<T, popoverContentProps<T>>,
) => {
const [local, rest] = splitProps(props as popoverContentProps, [
"class",
"children",
]);
return (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
class={cn(
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[expanded]:animate-in data-[closed]:animate-out data-[closed]:fade-out-0 data-[expanded]:fade-in-0 data-[closed]:zoom-out-95 data-[expanded]:zoom-in-95",
local.class,
)}
{...rest}
>
{local.children}
<PopoverPrimitive.CloseButton class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-[opacity,box-shadow] hover:opacity-100 focus:outline-none focus:ring-[1.5px] focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
class="h-4 w-4"
>
<path
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M18 6L6 18M6 6l12 12"
/>
<title>Close</title>
</svg>
</PopoverPrimitive.CloseButton>
</PopoverPrimitive.Content>
</PopoverPrimitive.Portal>
);
};
Install the following dependencies:
npm install @kobalte/core
Copy and paste the following code into your project:
import { cn } from "@/libs/cn";
import type { PolymorphicProps } from "@kobalte/core/polymorphic";
import type {
PopoverContentProps,
PopoverRootProps,
} from "@kobalte/core/popover";
import { Popover as PopoverPrimitive } from "@kobalte/core/popover";
import type { ParentProps, ValidComponent } from "solid-js";
import { mergeProps, splitProps } from "solid-js";
export const PopoverTrigger = PopoverPrimitive.Trigger;
export const PopoverTitle = PopoverPrimitive.Title;
export const PopoverDescription = PopoverPrimitive.Description;
export const Popover = (props: PopoverRootProps) => {
const merge = mergeProps<PopoverRootProps[]>(
{
gutter: 4,
flip: false,
},
props,
);
return <PopoverPrimitive {...merge} />;
};
type popoverContentProps<T extends ValidComponent = "div"> = ParentProps<
PopoverContentProps<T> & {
class?: string;
}
>;
export const PopoverContent = <T extends ValidComponent = "div">(
props: PolymorphicProps<T, popoverContentProps<T>>,
) => {
const [local, rest] = splitProps(props as popoverContentProps, [
"class",
"children",
]);
return (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
class={cn(
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[expanded]:(animate-in fade-in-0 zoom-in-95) data-[closed]:(animate-out fade-out-0 zoom-out-95)",
local.class,
)}
{...rest}
>
{local.children}
<PopoverPrimitive.CloseButton class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:(outline-none ring-1.5 ring-ring ring-offset-2) disabled:pointer-events-none bg-inherit transition-property-[opacity,box-shadow]">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
class="h-4 w-4"
>
<path
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M18 6L6 18M6 6l12 12"
/>
<title>Close</title>
</svg>
</PopoverPrimitive.CloseButton>
</PopoverPrimitive.Content>
</PopoverPrimitive.Portal>
);
};
Usage
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
<Popover>
<PopoverTrigger>Open</PopoverTrigger>
<PopoverContent>Place content for the popover here.</PopoverContent>
</Popover>