restructure project, add claudemd
This commit is contained in:
115
web/kit/Popovers.tsx
Normal file
115
web/kit/Popovers.tsx
Normal file
@@ -0,0 +1,115 @@
|
||||
import { createContext, JSXElement, useContext } from "solid-js";
|
||||
import { FloatingRoot, FloatingTrigger, FloatingContent, useFloatingHover, Placement } from "./Floating.tsx";
|
||||
|
||||
const POPOVER_CLS = "bg-white rounded-default shadow-lg border border-neutral-200";
|
||||
|
||||
interface PopoverProps {
|
||||
open?: boolean;
|
||||
onOpenChange?: (open: boolean) => void;
|
||||
placement?: Placement;
|
||||
offset?: number;
|
||||
// Nested floating that shouldn't close (or be closed by) an ancestor popover.
|
||||
standalone?: boolean;
|
||||
children?: JSXElement;
|
||||
}
|
||||
|
||||
interface HoverPopoverProps extends PopoverProps {
|
||||
hoverDelay?: number;
|
||||
hoverCloseDelay?: number;
|
||||
}
|
||||
|
||||
export function Popover(props: PopoverProps) {
|
||||
return (
|
||||
<FloatingRoot open={props.open} onOpenChange={(v: boolean) => props.onOpenChange?.(v)} placement={props.placement ?? "bottom-start"} offset={props.offset ?? 8} flip={true} shift={true} standalone={props.standalone}>
|
||||
{props.children}
|
||||
</FloatingRoot>
|
||||
);
|
||||
}
|
||||
|
||||
interface PopoverTriggerProps {
|
||||
class?: string;
|
||||
title?: string;
|
||||
children?: JSXElement;
|
||||
}
|
||||
|
||||
export function PopoverTrigger(props: PopoverTriggerProps) {
|
||||
return (
|
||||
<FloatingTrigger openOnHover={false} class={props.class || ""} title={props.title}>
|
||||
{props.children}
|
||||
</FloatingTrigger>
|
||||
);
|
||||
}
|
||||
|
||||
interface PopoverContentProps {
|
||||
class?: string;
|
||||
style?: Record<string, string | number>;
|
||||
children?: JSXElement;
|
||||
}
|
||||
|
||||
export function PopoverContent(props: PopoverContentProps) {
|
||||
return (
|
||||
<FloatingContent class={POPOVER_CLS + " " + (props.class || "")} style={props.style}>
|
||||
{props.children}
|
||||
</FloatingContent>
|
||||
);
|
||||
}
|
||||
|
||||
export function HoverPopover(props: HoverPopoverProps) {
|
||||
return (
|
||||
<FloatingRoot open={props.open} onOpenChange={(v: boolean) => props.onOpenChange?.(v)} placement={props.placement ?? "bottom-start"} offset={props.offset ?? 8} flip={true} shift={true} standalone={props.standalone}>
|
||||
<HoverPopoverInner hoverDelay={props.hoverDelay ?? 0} hoverCloseDelay={props.hoverCloseDelay ?? 150}>
|
||||
{props.children}
|
||||
</HoverPopoverInner>
|
||||
</FloatingRoot>
|
||||
);
|
||||
}
|
||||
|
||||
interface HoverPopoverContextValue {
|
||||
hoverDelay: number;
|
||||
hoverCloseDelay: number;
|
||||
}
|
||||
|
||||
const HoverPopoverContext = createContext<HoverPopoverContextValue | null>(null);
|
||||
|
||||
interface HoverPopoverInnerProps {
|
||||
hoverDelay: number;
|
||||
hoverCloseDelay: number;
|
||||
children?: JSXElement;
|
||||
}
|
||||
|
||||
function HoverPopoverInner(props: HoverPopoverInnerProps) {
|
||||
return (
|
||||
<HoverPopoverContext.Provider value={{
|
||||
get hoverDelay() { return props.hoverDelay; },
|
||||
get hoverCloseDelay() { return props.hoverCloseDelay; },
|
||||
}}>
|
||||
{props.children}
|
||||
</HoverPopoverContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
interface HoverPopoverTriggerProps {
|
||||
asChild?: boolean;
|
||||
class?: string;
|
||||
children?: JSXElement;
|
||||
}
|
||||
|
||||
export function HoverPopoverTrigger(props: HoverPopoverTriggerProps) {
|
||||
const ctx = useContext(HoverPopoverContext);
|
||||
return (
|
||||
<FloatingTrigger openOnHover={true} class={props.class || ""} hoverDelay={ctx?.hoverDelay ?? 0} hoverCloseDelay={ctx?.hoverCloseDelay ?? 150}>
|
||||
{props.children}
|
||||
</FloatingTrigger>
|
||||
);
|
||||
}
|
||||
|
||||
export function HoverPopoverContent(props: PopoverContentProps) {
|
||||
const ctx = useContext(HoverPopoverContext);
|
||||
const hoverProps = useFloatingHover(true, ctx?.hoverCloseDelay ?? 150);
|
||||
|
||||
return (
|
||||
<FloatingContent class={POPOVER_CLS + " " + (props.class || "")} style={props.style} onMouseEnter={hoverProps.onMouseEnter} onMouseLeave={hoverProps.onMouseLeave}>
|
||||
{props.children}
|
||||
</FloatingContent>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user