114 lines
3.7 KiB
Plaintext
114 lines
3.7 KiB
Plaintext
|
|
---
|
||
|
|
title: Overlays and positioning
|
||
|
|
description: Compose Dialog and Popover with Base UI render semantics and the local AnchoredSurface.
|
||
|
|
order: 12
|
||
|
|
toc:
|
||
|
|
- id: dialog
|
||
|
|
title: Dialog
|
||
|
|
- id: popover
|
||
|
|
title: Popover
|
||
|
|
- id: anchored-surface
|
||
|
|
title: Continuous tail
|
||
|
|
- id: positioning
|
||
|
|
title: Custom positioning
|
||
|
|
- id: choosing-an-overlay
|
||
|
|
title: Choose an overlay
|
||
|
|
---
|
||
|
|
|
||
|
|
## Dialog {#dialog}
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
import { Button } from "@workspace/ui/components/button"
|
||
|
|
import {
|
||
|
|
Dialog,
|
||
|
|
DialogContent,
|
||
|
|
DialogDescription,
|
||
|
|
DialogFooter,
|
||
|
|
DialogHeader,
|
||
|
|
DialogTitle,
|
||
|
|
DialogTrigger,
|
||
|
|
} from "@workspace/ui/components/dialog"
|
||
|
|
|
||
|
|
export function ProfileDialog() {
|
||
|
|
return (
|
||
|
|
<Dialog>
|
||
|
|
<DialogTrigger render={<Button variant="outline" />}>
|
||
|
|
Edit profile
|
||
|
|
</DialogTrigger>
|
||
|
|
<DialogContent>
|
||
|
|
<DialogHeader>
|
||
|
|
<DialogTitle>Edit profile</DialogTitle>
|
||
|
|
<DialogDescription>Update your public information.</DialogDescription>
|
||
|
|
</DialogHeader>
|
||
|
|
<div>Form content</div>
|
||
|
|
<DialogFooter>
|
||
|
|
<Button type="submit">Save</Button>
|
||
|
|
</DialogFooter>
|
||
|
|
</DialogContent>
|
||
|
|
</Dialog>
|
||
|
|
)
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
`DialogContent` already includes the portal, overlay, and default close button. The title and description connect to the underlying accessibility attributes, so do not replace them with unstructured `div` elements.
|
||
|
|
|
||
|
|
## Popover {#popover}
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
import { Button } from "@workspace/ui/components/button"
|
||
|
|
import {
|
||
|
|
Popover,
|
||
|
|
PopoverContent,
|
||
|
|
PopoverDescription,
|
||
|
|
PopoverTitle,
|
||
|
|
PopoverTrigger,
|
||
|
|
} from "@workspace/ui/components/popover"
|
||
|
|
|
||
|
|
;<Popover>
|
||
|
|
<PopoverTrigger render={<Button variant="outline" />}>
|
||
|
|
Open settings
|
||
|
|
</PopoverTrigger>
|
||
|
|
<PopoverContent align="end">
|
||
|
|
<PopoverTitle>Display settings</PopoverTitle>
|
||
|
|
<PopoverDescription>Choose the list density.</PopoverDescription>
|
||
|
|
</PopoverContent>
|
||
|
|
</Popover>
|
||
|
|
```
|
||
|
|
|
||
|
|
The local API continues to forward Base UI Popup and Positioner props. Pass `open` and `onOpenChange` to `Popover` when controlled state is required.
|
||
|
|
|
||
|
|
## Continuous tail {#anchored-surface}
|
||
|
|
|
||
|
|
The local `showArrow` is more than a triangular SVG. It renders `PopoverContent` through `AnchoredSurface`, producing one rounded surface with a continuous curved tail:
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
<PopoverContent
|
||
|
|
side="bottom"
|
||
|
|
showArrow={{ cornerRadius: "2xl", tailSize: "sm" }}
|
||
|
|
className="w-80 p-0"
|
||
|
|
viewportClassName="max-h-72 p-4"
|
||
|
|
>
|
||
|
|
{content}
|
||
|
|
</PopoverContent>
|
||
|
|
```
|
||
|
|
|
||
|
|
The outer surface remains `overflow: visible` so the tail is not clipped. Scrolling happens inside `data-slot="popover-viewport"`. Use `viewportClassName` when constraining content height or applying content padding.
|
||
|
|
|
||
|
|
`AnchoredSurface` can also render on its own, but it is visual only: it does not own anchor measurement, collision detection, focus, or a portal.
|
||
|
|
|
||
|
|
## Custom positioning {#positioning}
|
||
|
|
|
||
|
|
`PopoverContent` additionally exposes `anchor`, `positionMethod`, `arrowPadding`, `alignOffset`, and `sideOffset`. Pass virtual or custom anchors through the shared component instead of rebuilding the Base UI primitives.
|
||
|
|
|
||
|
|
For control outside React, create a handle with `createPopoverHandle<Payload>()` and connect it to the Root using Base UI's handle pattern.
|
||
|
|
|
||
|
|
## Choose an overlay {#choosing-an-overlay}
|
||
|
|
|
||
|
|
- Block background interaction with `Dialog` or `AlertDialog`.
|
||
|
|
- Use `Sheet` for a task surface entering from a screen edge and `Drawer` for a touch-oriented mobile panel.
|
||
|
|
- Use `Popover` for interactive content attached to a trigger.
|
||
|
|
- Use `HoverCard` for a preview revealed by hover or focus.
|
||
|
|
- Use `Tooltip` for short, non-interactive descriptions.
|
||
|
|
|
||
|
|
Compare basic usage with the [shadcn Popover documentation](https://ui.shadcn.com/docs/components/base/popover), but keep the Base UI `render` composition syntax.
|