Zaidan

Command Palette

Search for a command to run...

GitHub

Popover

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

Installation

CLI

Manual

Copy and paste the following code into your project.

import type { PolymorphicProps } from "@kobalte/core/polymorphic";
import * as PopoverPrimitive from "@kobalte/core/popover";
import type { ComponentProps, ValidComponent } from "solid-js";
import { mergeProps, splitProps } from "solid-js";
import { cn } from "~/lib/utils";
type PopoverProps = PopoverPrimitive.PopoverRootProps;
const Popover = (props: PopoverProps) => {
const mergedProps = mergeProps({ gutter: 4, placement: "bottom" } as const, props);
return <PopoverPrimitive.Root data-slot="popover" {...mergedProps} />;
};
type PopoverTriggerProps<T extends ValidComponent = "button"> = PolymorphicProps<
T,
PopoverPrimitive.PopoverTriggerProps<T>
>;
const PopoverTrigger = <T extends ValidComponent = "button">(props: PopoverTriggerProps<T>) => {
return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />;
};
type PopoverAnchorProps<T extends ValidComponent = "div"> = PolymorphicProps<
T,
PopoverPrimitive.PopoverAnchorProps<T>
>;
const PopoverAnchor = <T extends ValidComponent = "div">(props: PopoverAnchorProps<T>) => {
return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />;
};
type PopoverContentProps<T extends ValidComponent = "div"> = PolymorphicProps<
T,
PopoverPrimitive.PopoverContentProps<T>
> &
Pick<ComponentProps<T>, "class" | "children">;
const PopoverContent = <T extends ValidComponent = "div">(props: PopoverContentProps<T>) => {
const [local, others] = splitProps(props as PopoverContentProps, ["class", "children"]);
return (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
data-slot="popover-content"
class={cn(
"z-50 z-popover-content w-72 origin-(--kb-popover-content-transform-origin) outline-hidden",
local.class,
)}
{...others}
>
{local.children}
</PopoverPrimitive.Content>
</PopoverPrimitive.Portal>
);
};
type PopoverCloseButtonProps<T extends ValidComponent = "button"> = PolymorphicProps<
T,
PopoverPrimitive.PopoverCloseButtonProps<T>
> &
Pick<ComponentProps<T>, "class">;
const PopoverCloseButton = <T extends ValidComponent = "button">(
props: PopoverCloseButtonProps<T>,
) => {
const [local, others] = splitProps(props as PopoverCloseButtonProps, ["class"]);
return (
<PopoverPrimitive.CloseButton
data-slot="popover-close-button"
class={cn("z-popover-close-button", local.class)}
{...others}
/>
);
};
type PopoverHeaderProps = ComponentProps<"div"> & {
class?: string | undefined;
};
const PopoverHeader = (props: PopoverHeaderProps) => {
const [local, others] = splitProps(props, ["class"]);
return <div data-slot="popover-header" class={cn("z-popover-header", local.class)} {...others} />;
};
type PopoverTitleProps<T extends ValidComponent = "h2"> = PolymorphicProps<
T,
PopoverPrimitive.PopoverTitleProps<T>
> &
Pick<ComponentProps<T>, "class">;
const PopoverTitle = <T extends ValidComponent = "h2">(props: PopoverTitleProps<T>) => {
const [local, others] = splitProps(props as PopoverTitleProps, ["class"]);
return (
<PopoverPrimitive.Title
data-slot="popover-title"
class={cn("z-popover-title", local.class)}
{...others}
/>
);
};
type PopoverDescriptionProps<T extends ValidComponent = "p"> = PolymorphicProps<
T,
PopoverPrimitive.PopoverDescriptionProps<T>
> &
Pick<ComponentProps<T>, "class">;
const PopoverDescription = <T extends ValidComponent = "p">(props: PopoverDescriptionProps<T>) => {
const [local, others] = splitProps(props as PopoverDescriptionProps, ["class"]);
return (
<PopoverPrimitive.Description
data-slot="popover-description"
class={cn("z-popover-description", local.class)}
{...others}
/>
);
};
type PopoverArrowProps<T extends ValidComponent = "div"> = PolymorphicProps<
T,
PopoverPrimitive.PopoverArrowProps<T>
> &
Pick<ComponentProps<T>, "class">;
const PopoverArrow = <T extends ValidComponent = "div">(props: PopoverArrowProps<T>) => {
const [local, others] = splitProps(props as PopoverArrowProps, ["class"]);
return (
<PopoverPrimitive.Arrow
data-slot="popover-arrow"
class={cn("z-popover-arrow", local.class)}
{...others}
/>
);
};
export {
Popover,
PopoverAnchor,
PopoverArrow,
PopoverCloseButton,
PopoverContent,
PopoverDescription,
PopoverHeader,
PopoverTitle,
PopoverTrigger,
};

Examples

Here are the source code of all the examples from the preview page:

Basic

import { Button } from "~/components/ui/button";
import {
Popover,
PopoverContent,
PopoverDescription,
PopoverHeader,
PopoverTitle,
PopoverTrigger,
} from "~/components/ui/popover";
function PopoverBasic() {
return (
<Example title="Basic">
<Popover placement="bottom-start">
<PopoverTrigger as={Button} variant="outline" class="w-fit">
Open Popover
</PopoverTrigger>
<PopoverContent class="w-64">
<PopoverHeader>
<PopoverTitle>Dimensions</PopoverTitle>
<PopoverDescription>Set the dimensions for the layer.</PopoverDescription>
</PopoverHeader>
</PopoverContent>
</Popover>
</Example>
);
}

With Form

import { Button } from "~/components/ui/button";
import { Field, FieldGroup, FieldLabel } from "~/components/ui/field";
import { Input } from "~/components/ui/input";
import {
Popover,
PopoverContent,
PopoverDescription,
PopoverHeader,
PopoverTitle,
PopoverTrigger,
} from "~/components/ui/popover";
function PopoverWithForm() {
return (
<Example title="With Form">
<Popover>
<PopoverTrigger as={Button} variant="outline">
Open Popover
</PopoverTrigger>
<PopoverContent class="w-64">
<PopoverHeader>
<PopoverTitle>Dimensions</PopoverTitle>
<PopoverDescription>Set the dimensions for the layer.</PopoverDescription>
</PopoverHeader>
<FieldGroup class="gap-4">
<Field orientation="horizontal">
<FieldLabel for="width" class="w-1/2">
Width
</FieldLabel>
<Input id="width" value="100%" />
</Field>
<Field orientation="horizontal">
<FieldLabel for="height" class="w-1/2">
Height
</FieldLabel>
<Input id="height" value="25px" />
</Field>
</FieldGroup>
</PopoverContent>
</Popover>
</Example>
);
}

Alignments

import { Button } from "~/components/ui/button";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
function PopoverAlignments() {
return (
<Example title="Alignments">
<div class="flex gap-6">
<Popover placement="bottom-start">
<PopoverTrigger as={Button} variant="outline" size="sm">
Start
</PopoverTrigger>
<PopoverContent class="w-40">Aligned to start</PopoverContent>
</Popover>
<Popover placement="bottom">
<PopoverTrigger as={Button} variant="outline" size="sm">
Center
</PopoverTrigger>
<PopoverContent class="w-40">Aligned to center</PopoverContent>
</Popover>
<Popover placement="bottom-end">
<PopoverTrigger as={Button} variant="outline" size="sm">
End
</PopoverTrigger>
<PopoverContent class="w-40">Aligned to end</PopoverContent>
</Popover>
</div>
</Example>
);
}

In Dialog

import { Button } from "~/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "~/components/ui/dialog";
import {
Popover,
PopoverContent,
PopoverDescription,
PopoverHeader,
PopoverTitle,
PopoverTrigger,
} from "~/components/ui/popover";
function PopoverInDialog() {
return (
<Example title="In Dialog">
<Dialog>
<DialogTrigger as={Button} variant="outline">
Open Dialog
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Popover Example</DialogTitle>
<DialogDescription>Click the button below to see the popover.</DialogDescription>
</DialogHeader>
<Popover placement="bottom-start">
<PopoverTrigger as={Button} variant="outline" class="w-fit">
Open Popover
</PopoverTrigger>
<PopoverContent>
<PopoverHeader>
<PopoverTitle>Popover in Dialog</PopoverTitle>
<PopoverDescription>
This popover appears inside a dialog. Click the button to open it.
</PopoverDescription>
</PopoverHeader>
</PopoverContent>
</Popover>
</DialogContent>
</Dialog>
</Example>
);
}