Components
Popover
A click-toggled floating panel, wrapping Morphos's Popover primitive.
Installation
npx kosmesis add popoverpnpm dlx kosmesis add popoveryarn dlx kosmesis add popoverbunx kosmesis add popoverInstall the following dependencies:
npm install @morphos/overlayspnpm add @morphos/overlaysyarn add @morphos/overlaysbun add @morphos/overlaysCopy and paste the following code into your project.
import { StatelessComponent } from "@praxisjs/core";import { Component } from "@praxisjs/decorators";import { PopoverContent as MorphosPopoverContent, type PopoverContentProps as MorphosPopoverContentProps } from "@morphos/overlays";import { cn } from "@/lib/utils";/** * `Popover` and `PopoverTrigger` are re-exported directly — same reasoning as `Tooltip`: the root * is always instantiated directly (`@State() popover = new Popover()`), never mounted via JSX, so * wrapping it would break `.isOpen`/`.toggle()`/`.closePopover()`. */export { Popover, PopoverTrigger, type PopoverProps, type PopoverTriggerProps,} from "@morphos/overlays";export type PopoverContentProps = MorphosPopoverContentProps;@Component()export class PopoverContent extends StatelessComponent<PopoverContentProps> { render() { const { class: cls, ...rest } = this.props; return ( <MorphosPopoverContent class={cn( "z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none", "data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95", cls, )} {...rest} /> ); }}Install the following dependencies:
npm install @morphos/overlays @praxisjs/csspnpm add @morphos/overlays @praxisjs/cssyarn add @morphos/overlays @praxisjs/cssbun add @morphos/overlays @praxisjs/cssCopy and paste the following code into your project.
import { StatelessComponent } from "@praxisjs/core";import { cx, keyframes, Stylesheet, Styled, tokenVars } from "@praxisjs/css";import { Component } from "@praxisjs/decorators";import { PopoverContent as MorphosPopoverContent, type PopoverContentProps as MorphosPopoverContentProps } from "@morphos/overlays";import { KosmesisTokens } from "@/lib/kosmesis-theme";const t = tokenVars(KosmesisTokens);const popIn = keyframes("kosmesis-pop-in", { from: { opacity: "0", transform: "scale(0.95)" }, to: { opacity: "1", transform: "scale(1)" },});class PopoverStyles extends Stylesheet { $content = this.css({ position: "relative", zIndex: 50, width: "18rem", borderRadius: `calc(${t.radius} - 2px)`, border: `1px solid ${t.border}`, backgroundColor: t.popover, padding: "1rem", color: t.popoverForeground, boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1)", outline: "none", }).on("&[data-open]", { animation: `${popIn} 100ms ease-out` });}/** * `Popover` and `PopoverTrigger` are re-exported directly — same reasoning as `Tooltip`: the root * is always instantiated directly (`@State() popover = new Popover()`), never mounted via JSX, so * wrapping it would break `.isOpen`/`.toggle()`/`.closePopover()`. */export { Popover, PopoverTrigger, type PopoverProps, type PopoverTriggerProps } from "@morphos/overlays";export type PopoverContentProps = MorphosPopoverContentProps;@Component()export class PopoverContent extends StatelessComponent<PopoverContentProps> { @Styled(PopoverStyles) $s!: PopoverStyles; render() { const { class: cls, ...rest } = this.props; return <MorphosPopoverContent class={cx(this.$s.$content, cls)} {...rest} />; }}Examples
Usage
import { Popover, PopoverContent, PopoverTrigger } from "@morphos/overlays";
import { buttonVariants } from "@/components/ui/button";
@Component()
class Settings extends StatefulComponent {
@State() popover = new Popover();
render() {
return (
<>
<PopoverTrigger popover={this.popover} class={buttonVariants({ variant: "outline" })}>
Open popover
</PopoverTrigger>
<PopoverContent popover={this.popover}>
<p>Place any content here.</p>
</PopoverContent>
</>
);
}
}Morphos's PopoverTrigger always renders its own <button> — there's no asChild merge like
Radix's. Style it directly with buttonVariants() (imported from ./button) instead of
nesting a separate Button inside it, which would produce invalid nested <button> elements.
Props
Popover
Re-exported directly from @morphos/overlays.
| Prop | Type | Default |
|---|---|---|
open | boolean | — controlled open state |
defaultOpen | boolean | — |
onOpenChange | (open: boolean) => void | — |
closeOnEscape | boolean | — |
closeOnOutsideClick | boolean | — |
side | "top" | "right" | "bottom" | "left" | "bottom" |
align | "start" | "center" | "end" | "start" |
sideOffset | number | 4 |
PopoverTrigger
| Prop | Type | Default |
|---|---|---|
popover | Popover | — required |
PopoverContent
| Prop | Type | Default |
|---|---|---|
popover | Popover | — required |
aria-label | string | — |
aria-labelledby | string | — |