COMPONENTS/OVERLAYS
Popover.
A useful detail, close at hand.
In practice
Compose PopoverTrigger and PopoverContent, plus Title and Description where appropriate. Supports controlled open state.
Installation
Install Coal once. Components and TypeScript declarations are included. React 19 and React DOM 19 are peer dependencies.
Terminal · local package
npm install http://localhost:3100/downloads/chlohal-coal-ui-0.5.0.tgzThis installs the local package. It is not yet published on npm. See installation for stylesheet setup and integration.
Usage
example.tsx
"use client";
import * as React from "react";
import "@chlohal/coal-ui/styles.css";
import { Bell } from "lucide-react";
import { Button, Popover, PopoverTrigger, PopoverContent, PopoverTitle, PopoverDescription } from "@chlohal/coal-ui";
export default function Example() {
return (<Popover>
<PopoverTrigger render={<Button variant="outline"/>}>
<Bell size={14}/>
What's new
</PopoverTrigger>
<PopoverContent>
<PopoverTitle>
A quieter workspace.
</PopoverTitle>
<PopoverDescription>
Your components now share the same warm palette.
</PopoverDescription>
</PopoverContent>
</Popover>);
}
Source
The original Coal implementation. Use the package export to integrate it.
packages/react/src/popover.tsx
"use client";
import * as React from "react";
import { Action, type ActionProps } from "./internal.js";
import {
useFloating,
FloatingContent,
type FloatingContentProps,
} from "./floating.js";
export {
FloatingRoot as Popover,
FloatingTrigger as PopoverTrigger,
} from "./floating.js";
export function PopoverContent(props: FloatingContentProps) {
const c = useFloating();
return (
<FloatingContent
role="dialog"
aria-labelledby={`${c.id}-title`}
aria-describedby={`${c.id}-description`}
{...props}
/>
);
}
export function PopoverTitle(props: React.ComponentPropsWithRef<"h2">) {
const c = useFloating();
return <h2 className="coal-popover-title" {...props} id={`${c.id}-title`} />;
}
export function PopoverDescription(props: React.ComponentPropsWithRef<"p">) {
const c = useFloating();
return (
<p
className="coal-popover-description"
{...props}
id={`${c.id}-description`}
/>
);
}
export function PopoverClose({ onClick, ...props }: ActionProps) {
const c = useFloating();
return (
<Action
{...props}
onClick={(e) => {
onClick?.(e);
if (!e.defaultPrevented) c.close();
}}
/>
);
}
Accessibility checklist
- Provide an accessible name for controls, including icon-only buttons.
- Check keyboard navigation, visible focus and disabled states in your application.
- Do not rely on color alone to communicate status.